Skip to content

Commit 53a0397

Browse files
committed
Auto merge of rust-lang#115361 - compiler-errors:param, r=cjgillot
Don't manually compute param indices when adding implicit `Sized` and `ConstParamHasTy` We can just use resolve_bound_vars to compute these indices faithfully. This also makes the code easier to support where clauses on `non_lifetime_binders` (like `where for<T: Debug> ...`, etc, which I've got a [WIP implementation of](rust-lang/rust@master...compiler-errors:rust:non-lifetime-binder-where-clauses)). r? `@cjgillot`
2 parents b89d7d6 + c5d0f6c commit 53a0397

File tree

3 files changed

+145
-129
lines changed

3 files changed

+145
-129
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+52-21
Original file line numberDiff line numberDiff line change
@@ -2205,27 +2205,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22052205
err.span_note(span, format!("type parameter `{name}` defined here"));
22062206
}
22072207
});
2208-
2209-
match tcx.named_bound_var(hir_id) {
2210-
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
2211-
let name =
2212-
tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
2213-
let br = ty::BoundTy {
2214-
var: ty::BoundVar::from_u32(index),
2215-
kind: ty::BoundTyKind::Param(def_id, name),
2216-
};
2217-
Ty::new_bound(tcx, debruijn, br)
2218-
}
2219-
Some(rbv::ResolvedArg::EarlyBound(_)) => {
2220-
let def_id = def_id.expect_local();
2221-
let item_def_id = tcx.hir().ty_param_owner(def_id);
2222-
let generics = tcx.generics_of(item_def_id);
2223-
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
2224-
Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
2225-
}
2226-
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
2227-
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
2228-
}
2208+
self.hir_id_to_bound_ty(hir_id)
22292209
}
22302210
Res::SelfTyParam { .. } => {
22312211
// `Self` in trait or type alias.
@@ -2394,6 +2374,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23942374
}
23952375
}
23962376

2377+
// Converts a hir id corresponding to a type parameter to
2378+
// a early-bound `ty::Param` or late-bound `ty::Bound`.
2379+
pub(crate) fn hir_id_to_bound_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
2380+
let tcx = self.tcx();
2381+
match tcx.named_bound_var(hir_id) {
2382+
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
2383+
let name = tcx.item_name(def_id);
2384+
let br = ty::BoundTy {
2385+
var: ty::BoundVar::from_u32(index),
2386+
kind: ty::BoundTyKind::Param(def_id, name),
2387+
};
2388+
Ty::new_bound(tcx, debruijn, br)
2389+
}
2390+
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
2391+
let def_id = def_id.expect_local();
2392+
let item_def_id = tcx.hir().ty_param_owner(def_id);
2393+
let generics = tcx.generics_of(item_def_id);
2394+
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
2395+
Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
2396+
}
2397+
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
2398+
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
2399+
}
2400+
}
2401+
2402+
// Converts a hir id corresponding to a const parameter to
2403+
// a early-bound `ConstKind::Param` or late-bound `ConstKind::Bound`.
2404+
pub(crate) fn hir_id_to_bound_const(
2405+
&self,
2406+
hir_id: hir::HirId,
2407+
param_ty: Ty<'tcx>,
2408+
) -> Const<'tcx> {
2409+
let tcx = self.tcx();
2410+
match tcx.named_bound_var(hir_id) {
2411+
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
2412+
// Find the name and index of the const parameter by indexing the generics of
2413+
// the parent item and construct a `ParamConst`.
2414+
let item_def_id = tcx.parent(def_id);
2415+
let generics = tcx.generics_of(item_def_id);
2416+
let index = generics.param_def_id_to_index[&def_id];
2417+
let name = tcx.item_name(def_id);
2418+
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)
2419+
}
2420+
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
2421+
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty)
2422+
}
2423+
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty),
2424+
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
2425+
}
2426+
}
2427+
23972428
/// Parses the programmer's textual representation of a type into our
23982429
/// internal notion of a type.
23992430
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+5-29
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
162162
};
163163

164164
let generics = tcx.generics_of(def_id);
165-
let parent_count = generics.parent_count as u32;
166-
let has_own_self = generics.has_self && parent_count == 0;
167165

168166
// Below we'll consider the bounds on the type parameters (including `Self`)
169167
// and the explicit where-clauses, but to get the full set of predicates
@@ -189,17 +187,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
189187
predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id)));
190188
}
191189

192-
// Collect the region predicates that were declared inline as
193-
// well. In the case of parameters declared on a fn or method, we
194-
// have to be careful to only iterate over early-bound regions.
195-
let mut index = parent_count
196-
+ has_own_self as u32
197-
+ super::early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
198-
199-
trace!(?predicates);
200-
trace!(?ast_generics);
201-
trace!(?generics);
202-
203190
// Collect the predicates that were written inline by the user on each
204191
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
205192
// for each const parameter.
@@ -208,10 +195,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
208195
// We already dealt with early bound lifetimes above.
209196
GenericParamKind::Lifetime { .. } => (),
210197
GenericParamKind::Type { .. } => {
211-
let name = param.name.ident().name;
212-
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
213-
index += 1;
214-
198+
let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id);
215199
let mut bounds = Bounds::default();
216200
// Params are implicitly sized unless a `?Sized` bound is found
217201
icx.astconv().add_implicitly_sized(
@@ -225,23 +209,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
225209
predicates.extend(bounds.clauses());
226210
trace!(?predicates);
227211
}
228-
GenericParamKind::Const { .. } => {
229-
let name = param.name.ident().name;
230-
let param_const = ty::ParamConst::new(index, name);
231-
212+
hir::GenericParamKind::Const { .. } => {
232213
let ct_ty = tcx
233214
.type_of(param.def_id.to_def_id())
234215
.no_bound_vars()
235216
.expect("const parameters cannot be generic");
236-
237-
let ct = ty::Const::new_param(tcx, param_const, ct_ty);
238-
217+
let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty);
239218
predicates.insert((
240219
ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
241220
param.span,
242221
));
243-
244-
index += 1;
245222
}
246223
}
247224
}
@@ -252,8 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
252229
match predicate {
253230
hir::WherePredicate::BoundPredicate(bound_pred) => {
254231
let ty = icx.to_ty(bound_pred.bounded_ty);
255-
let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id);
256-
232+
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
257233
// Keep the type around in a dummy predicate, in case of no bounds.
258234
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
259235
// is still checked for WF.
@@ -296,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
296272
_ => bug!(),
297273
};
298274
let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
299-
.to_predicate(icx.tcx);
275+
.to_predicate(tcx);
300276
(pred, span)
301277
}))
302278
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+88-79
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
849849
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
850850
let scope = Scope::TraitRefBoundary { s: self.scope };
851851
self.with(scope, |this| {
852+
walk_list!(this, visit_generic_param, generics.params);
852853
for param in generics.params {
853854
match param.kind {
854855
GenericParamKind::Lifetime { .. } => {}
@@ -865,90 +866,86 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
865866
}
866867
}
867868
}
868-
for predicate in generics.predicates {
869-
match predicate {
870-
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
871-
hir_id,
872-
bounded_ty,
873-
bounds,
874-
bound_generic_params,
875-
origin,
876-
..
877-
}) => {
878-
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
879-
bound_generic_params
880-
.iter()
881-
.enumerate()
882-
.map(|(late_bound_idx, param)| {
883-
let pair = ResolvedArg::late(late_bound_idx as u32, param);
884-
let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
885-
(pair, r)
886-
})
887-
.unzip();
888-
this.record_late_bound_vars(hir_id, binders.clone());
889-
// Even if there are no lifetimes defined here, we still wrap it in a binder
890-
// scope. If there happens to be a nested poly trait ref (an error), that
891-
// will be `Concatenating` anyways, so we don't have to worry about the depth
892-
// being wrong.
893-
let scope = Scope::Binder {
894-
hir_id,
895-
bound_vars,
896-
s: this.scope,
897-
scope_type: BinderScopeType::Normal,
898-
where_bound_origin: Some(origin),
899-
};
900-
this.with(scope, |this| {
901-
this.visit_ty(&bounded_ty);
902-
walk_list!(this, visit_param_bound, bounds);
869+
walk_list!(this, visit_where_predicate, generics.predicates);
870+
})
871+
}
872+
873+
fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
874+
match predicate {
875+
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
876+
hir_id,
877+
bounded_ty,
878+
bounds,
879+
bound_generic_params,
880+
origin,
881+
..
882+
}) => {
883+
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
884+
bound_generic_params
885+
.iter()
886+
.enumerate()
887+
.map(|(late_bound_idx, param)| {
888+
let pair = ResolvedArg::late(late_bound_idx as u32, param);
889+
let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
890+
(pair, r)
903891
})
904-
}
905-
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
906-
lifetime,
907-
bounds,
908-
..
909-
}) => {
910-
this.visit_lifetime(lifetime);
911-
walk_list!(this, visit_param_bound, bounds);
912-
913-
if lifetime.res != hir::LifetimeName::Static {
914-
for bound in bounds {
915-
let hir::GenericBound::Outlives(lt) = bound else {
916-
continue;
917-
};
918-
if lt.res != hir::LifetimeName::Static {
919-
continue;
920-
}
921-
this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
922-
this.tcx.struct_span_lint_hir(
923-
lint::builtin::UNUSED_LIFETIMES,
924-
lifetime.hir_id,
925-
lifetime.ident.span,
926-
format!(
927-
"unnecessary lifetime parameter `{}`",
928-
lifetime.ident
929-
),
930-
|lint| {
931-
let help = format!(
932-
"you can use the `'static` lifetime directly, in place of `{}`",
933-
lifetime.ident,
934-
);
935-
lint.help(help)
936-
},
937-
);
938-
}
892+
.unzip();
893+
self.record_late_bound_vars(hir_id, binders.clone());
894+
// Even if there are no lifetimes defined here, we still wrap it in a binder
895+
// scope. If there happens to be a nested poly trait ref (an error), that
896+
// will be `Concatenating` anyways, so we don't have to worry about the depth
897+
// being wrong.
898+
let scope = Scope::Binder {
899+
hir_id,
900+
bound_vars,
901+
s: self.scope,
902+
scope_type: BinderScopeType::Normal,
903+
where_bound_origin: Some(origin),
904+
};
905+
self.with(scope, |this| {
906+
walk_list!(this, visit_generic_param, bound_generic_params);
907+
this.visit_ty(&bounded_ty);
908+
walk_list!(this, visit_param_bound, bounds);
909+
})
910+
}
911+
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
912+
lifetime,
913+
bounds,
914+
..
915+
}) => {
916+
self.visit_lifetime(lifetime);
917+
walk_list!(self, visit_param_bound, bounds);
918+
919+
if lifetime.res != hir::LifetimeName::Static {
920+
for bound in bounds {
921+
let hir::GenericBound::Outlives(lt) = bound else {
922+
continue;
923+
};
924+
if lt.res != hir::LifetimeName::Static {
925+
continue;
939926
}
940-
}
941-
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
942-
lhs_ty,
943-
rhs_ty,
944-
..
945-
}) => {
946-
this.visit_ty(lhs_ty);
947-
this.visit_ty(rhs_ty);
927+
self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
928+
self.tcx.struct_span_lint_hir(
929+
lint::builtin::UNUSED_LIFETIMES,
930+
lifetime.hir_id,
931+
lifetime.ident.span,
932+
format!("unnecessary lifetime parameter `{}`", lifetime.ident),
933+
|lint| {
934+
let help = format!(
935+
"you can use the `'static` lifetime directly, in place of `{}`",
936+
lifetime.ident,
937+
);
938+
lint.help(help)
939+
},
940+
);
948941
}
949942
}
950943
}
951-
})
944+
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
945+
self.visit_ty(lhs_ty);
946+
self.visit_ty(rhs_ty);
947+
}
948+
}
952949
}
953950

954951
fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
@@ -986,6 +983,18 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
986983
intravisit::walk_anon_const(this, c);
987984
});
988985
}
986+
987+
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
988+
match p.kind {
989+
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
990+
self.resolve_type_ref(p.def_id, p.hir_id);
991+
}
992+
GenericParamKind::Lifetime { .. } => {
993+
// No need to resolve lifetime params, we don't use them for things
994+
// like implicit `?Sized` or const-param-has-ty predicates.
995+
}
996+
}
997+
}
989998
}
990999

9911000
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {

0 commit comments

Comments
 (0)