diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7a6856fb1f4b7..90f64e18632a1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2205,27 +2205,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_note(span, format!("type parameter `{name}` defined here")); } }); - - match tcx.named_bound_var(hir_id) { - Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { - let name = - tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); - let br = ty::BoundTy { - var: ty::BoundVar::from_u32(index), - kind: ty::BoundTyKind::Param(def_id, name), - }; - Ty::new_bound(tcx, debruijn, br) - } - Some(rbv::ResolvedArg::EarlyBound(_)) => { - let def_id = def_id.expect_local(); - let item_def_id = tcx.hir().ty_param_owner(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) - } - Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), - arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), - } + self.hir_id_to_bound_ty(hir_id) } Res::SelfTyParam { .. } => { // `Self` in trait or type alias. @@ -2394,6 +2374,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + // Converts a hir id corresponding to a type parameter to + // a early-bound `ty::Param` or late-bound `ty::Bound`. + pub(crate) fn hir_id_to_bound_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> { + let tcx = self.tcx(); + match tcx.named_bound_var(hir_id) { + Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => { + let name = tcx.item_name(def_id); + let br = ty::BoundTy { + var: ty::BoundVar::from_u32(index), + kind: ty::BoundTyKind::Param(def_id, name), + }; + Ty::new_bound(tcx, debruijn, br) + } + Some(rbv::ResolvedArg::EarlyBound(def_id)) => { + let def_id = def_id.expect_local(); + let item_def_id = tcx.hir().ty_param_owner(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id.to_def_id()]; + Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) + } + Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), + arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), + } + } + + // Converts a hir id corresponding to a const parameter to + // a early-bound `ConstKind::Param` or late-bound `ConstKind::Bound`. + pub(crate) fn hir_id_to_bound_const( + &self, + hir_id: hir::HirId, + param_ty: Ty<'tcx>, + ) -> Const<'tcx> { + let tcx = self.tcx(); + match tcx.named_bound_var(hir_id) { + Some(rbv::ResolvedArg::EarlyBound(def_id)) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let item_def_id = tcx.parent(def_id); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + let name = tcx.item_name(def_id); + ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty) + } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { + ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty) + } + Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty), + arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id), + } + } + /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 495e663666cb9..1298c08608716 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -162,8 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }; let generics = tcx.generics_of(def_id); - let parent_count = generics.parent_count as u32; - let has_own_self = generics.has_self && parent_count == 0; // Below we'll consider the bounds on the type parameters (including `Self`) // 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 predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); } - // Collect the region predicates that were declared inline as - // well. In the case of parameters declared on a fn or method, we - // have to be careful to only iterate over early-bound regions. - let mut index = parent_count - + has_own_self as u32 - + super::early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32; - - trace!(?predicates); - trace!(?ast_generics); - trace!(?generics); - // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). Also add `ConstArgHasType` predicates // for each const parameter. @@ -208,10 +195,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // We already dealt with early bound lifetimes above. GenericParamKind::Lifetime { .. } => (), GenericParamKind::Type { .. } => { - let name = param.name.ident().name; - let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); - index += 1; - + let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id); let mut bounds = Bounds::default(); // Params are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized( @@ -225,23 +209,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.extend(bounds.clauses()); trace!(?predicates); } - GenericParamKind::Const { .. } => { - let name = param.name.ident().name; - let param_const = ty::ParamConst::new(index, name); - + hir::GenericParamKind::Const { .. } => { let ct_ty = tcx .type_of(param.def_id.to_def_id()) .no_bound_vars() .expect("const parameters cannot be generic"); - - let ct = ty::Const::new_param(tcx, param_const, ct_ty); - + let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty); predicates.insert(( ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), param.span, )); - - index += 1; } } } @@ -252,8 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(bound_pred.bounded_ty); - let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id); - + let bound_vars = tcx.late_bound_vars(bound_pred.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` // is still checked for WF. @@ -296,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen _ => bug!(), }; let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) - .to_predicate(icx.tcx); + .to_predicate(tcx); (pred, span) })) } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 6dd0c840de632..2bee272772538 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -849,6 +849,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { + walk_list!(this, visit_generic_param, generics.params); for param in generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} @@ -865,90 +866,86 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } } - for predicate in generics.predicates { - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - hir_id, - bounded_ty, - bounds, - bound_generic_params, - origin, - .. - }) => { - let (bound_vars, binders): (FxIndexMap, Vec<_>) = - bound_generic_params - .iter() - .enumerate() - .map(|(late_bound_idx, param)| { - let pair = ResolvedArg::late(late_bound_idx as u32, param); - let r = late_arg_as_bound_arg(this.tcx, &pair.1, param); - (pair, r) - }) - .unzip(); - this.record_late_bound_vars(hir_id, binders.clone()); - // Even if there are no lifetimes defined here, we still wrap it in a binder - // scope. If there happens to be a nested poly trait ref (an error), that - // will be `Concatenating` anyways, so we don't have to worry about the depth - // being wrong. - let scope = Scope::Binder { - hir_id, - bound_vars, - s: this.scope, - scope_type: BinderScopeType::Normal, - where_bound_origin: Some(origin), - }; - this.with(scope, |this| { - this.visit_ty(&bounded_ty); - walk_list!(this, visit_param_bound, bounds); + walk_list!(this, visit_where_predicate, generics.predicates); + }) + } + + fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) { + match predicate { + &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id, + bounded_ty, + bounds, + bound_generic_params, + origin, + .. + }) => { + let (bound_vars, binders): (FxIndexMap, Vec<_>) = + bound_generic_params + .iter() + .enumerate() + .map(|(late_bound_idx, param)| { + let pair = ResolvedArg::late(late_bound_idx as u32, param); + let r = late_arg_as_bound_arg(self.tcx, &pair.1, param); + (pair, r) }) - } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - lifetime, - bounds, - .. - }) => { - this.visit_lifetime(lifetime); - walk_list!(this, visit_param_bound, bounds); - - if lifetime.res != hir::LifetimeName::Static { - for bound in bounds { - let hir::GenericBound::Outlives(lt) = bound else { - continue; - }; - if lt.res != hir::LifetimeName::Static { - continue; - } - this.insert_lifetime(lt, ResolvedArg::StaticLifetime); - this.tcx.struct_span_lint_hir( - lint::builtin::UNUSED_LIFETIMES, - lifetime.hir_id, - lifetime.ident.span, - format!( - "unnecessary lifetime parameter `{}`", - lifetime.ident - ), - |lint| { - let help = format!( - "you can use the `'static` lifetime directly, in place of `{}`", - lifetime.ident, - ); - lint.help(help) - }, - ); - } + .unzip(); + self.record_late_bound_vars(hir_id, binders.clone()); + // Even if there are no lifetimes defined here, we still wrap it in a binder + // scope. If there happens to be a nested poly trait ref (an error), that + // will be `Concatenating` anyways, so we don't have to worry about the depth + // being wrong. + let scope = Scope::Binder { + hir_id, + bound_vars, + s: self.scope, + scope_type: BinderScopeType::Normal, + where_bound_origin: Some(origin), + }; + self.with(scope, |this| { + walk_list!(this, visit_generic_param, bound_generic_params); + this.visit_ty(&bounded_ty); + walk_list!(this, visit_param_bound, bounds); + }) + } + &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + lifetime, + bounds, + .. + }) => { + self.visit_lifetime(lifetime); + walk_list!(self, visit_param_bound, bounds); + + if lifetime.res != hir::LifetimeName::Static { + for bound in bounds { + let hir::GenericBound::Outlives(lt) = bound else { + continue; + }; + if lt.res != hir::LifetimeName::Static { + continue; } - } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - lhs_ty, - rhs_ty, - .. - }) => { - this.visit_ty(lhs_ty); - this.visit_ty(rhs_ty); + self.insert_lifetime(lt, ResolvedArg::StaticLifetime); + self.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_LIFETIMES, + lifetime.hir_id, + lifetime.ident.span, + format!("unnecessary lifetime parameter `{}`", lifetime.ident), + |lint| { + let help = format!( + "you can use the `'static` lifetime directly, in place of `{}`", + lifetime.ident, + ); + lint.help(help) + }, + ); } } } - }) + &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + self.visit_ty(lhs_ty); + self.visit_ty(rhs_ty); + } + } } fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { @@ -986,6 +983,18 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { intravisit::walk_anon_const(this, c); }); } + + fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) { + match p.kind { + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { + self.resolve_type_ref(p.def_id, p.hir_id); + } + GenericParamKind::Lifetime { .. } => { + // No need to resolve lifetime params, we don't use them for things + // like implicit `?Sized` or const-param-has-ty predicates. + } + } + } } fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {