diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index da779a165690b..0b81f4693712f 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -43,7 +43,7 @@ fn associated_type_bounds<'tcx>( match filter { PredicateFilter::All | PredicateFilter::SelfOnly - | PredicateFilter::SelfThatDefines(_) + | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); } @@ -122,7 +122,7 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>( PredicateFilter::SelfOnly => { return None; } - PredicateFilter::SelfThatDefines(_) + PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfConstIfConst | PredicateFilter::SelfAndAssociatedTypeBounds | PredicateFilter::ConstIfConst => { @@ -329,7 +329,7 @@ fn opaque_type_bounds<'tcx>( match filter { PredicateFilter::All | PredicateFilter::SelfOnly - | PredicateFilter::SelfThatDefines(_) + | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { // Associated types are implicitly sized unless a `?Sized` bound is found icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index efe84e0006fd4..7ce12d48160aa 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -557,7 +557,11 @@ pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>( tcx: TyCtxt<'tcx>, (trait_def_id, assoc_name): (DefId, Ident), ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name)) + implied_predicates_with_filter( + tcx, + trait_def_id, + PredicateFilter::SelfTraitThatDefines(assoc_name), + ) } pub(super) fn explicit_implied_predicates_of<'tcx>( @@ -586,7 +590,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let Some(trait_def_id) = trait_def_id.as_local() else { // if `assoc_name` is None, then the query should've been redirected to an // external provider - assert_matches!(filter, PredicateFilter::SelfThatDefines(_)); + assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_)); return tcx.explicit_super_predicates_of(trait_def_id); }; @@ -606,12 +610,8 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let mut bounds = Bounds::default(); icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); - let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics( - generics, - item.owner_id.def_id, - self_param_ty, - filter, - ); + let where_bounds_that_match = + icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter); // Combine the two lists to form the complete set of superbounds: let implied_bounds = @@ -652,7 +652,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( } // Make sure when elaborating supertraits, probing for associated types, etc., -// we really truly are elaborating clauses that have `Self` as their self type. +// we really truly are elaborating clauses that have `ty` as their self type. // This is very important since downstream code relies on this being correct. pub(super) fn assert_only_contains_predicates_from<'tcx>( filter: PredicateFilter, @@ -664,7 +664,7 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( } match filter { - PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => { + PredicateFilter::SelfOnly => { for (clause, _) in bounds { match clause.kind().skip_binder() { ty::ClauseKind::Trait(trait_predicate) => { @@ -704,6 +704,33 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( } } } + PredicateFilter::SelfTraitThatDefines(_) => { + for (clause, _) in bounds { + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(trait_predicate) => { + assert_eq!( + trait_predicate.self_ty(), + ty, + "expected `Self` predicate when computing \ + `{filter:?}` implied bounds: {clause:?}" + ); + } + + ty::ClauseKind::Projection(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::HostEffect(..) => { + bug!( + "unexpected non-`Self` predicate when computing \ + `{filter:?}` implied bounds: {clause:?}" + ); + } + } + } + } PredicateFilter::ConstIfConst => { for (clause, _) in bounds { match clause.kind().skip_binder() { @@ -767,21 +794,16 @@ pub(super) fn type_param_predicates<'tcx>( None => {} } - use rustc_hir::*; - use rustc_middle::ty::Ty; - // In the HIR, bounds can derive from two places. Either // written inline like `` or in a where-clause like // `where T: Foo`. let param_id = tcx.local_def_id_to_hir_id(def_id); let param_owner = tcx.hir().ty_param_owner(def_id); - let generics = tcx.generics_of(param_owner); - let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - let ty = Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner { + // FIXME: Shouldn't this be unreachable? None } else { tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local()) @@ -801,8 +823,9 @@ pub(super) fn type_param_predicates<'tcx>( let Some(hir_generics) = hir_node.generics() else { return result; }; + if let Node::Item(item) = hir_node - && let ItemKind::Trait(..) = item.kind + && let hir::ItemKind::Trait(..) = item.kind // Implied `Self: Trait` and supertrait bounds. && param_id == item_hir_id { @@ -811,23 +834,34 @@ pub(super) fn type_param_predicates<'tcx>( } let icx = ItemCtxt::new(tcx, item_def_id); - let extra_predicates = extend.into_iter().chain( - icx.probe_ty_param_bounds_in_generics( - hir_generics, - def_id, - ty, - PredicateFilter::SelfThatDefines(assoc_name), - ) - .into_iter() - .filter(|(predicate, _)| match predicate.kind().skip_binder() { - ty::ClauseKind::Trait(data) => data.self_ty().is_param(index), - _ => false, - }), + let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics( + hir_generics, + def_id, + PredicateFilter::SelfTraitThatDefines(assoc_name), + )); + + let bounds = + &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates)); + + // Double check that the bounds *only* contain `SelfTy: Trait` preds. + let self_ty = match tcx.def_kind(def_id) { + DefKind::TyParam => Ty::new_param( + tcx, + tcx.generics_of(item_def_id) + .param_def_id_to_index(tcx, def_id.to_def_id()) + .expect("expected generic param to be owned by item"), + tcx.item_name(def_id.to_def_id()), + ), + DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param, + _ => unreachable!(), + }; + assert_only_contains_predicates_from( + PredicateFilter::SelfTraitThatDefines(assoc_name), + bounds, + self_ty, ); - ty::EarlyBinder::bind( - tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates)), - ) + ty::EarlyBinder::bind(bounds) } impl<'tcx> ItemCtxt<'tcx> { @@ -841,7 +875,6 @@ impl<'tcx> ItemCtxt<'tcx> { &self, hir_generics: &'tcx hir::Generics<'tcx>, param_def_id: LocalDefId, - ty: Ty<'tcx>, filter: PredicateFilter, ) -> Vec<(ty::Clause<'tcx>, Span)> { let mut bounds = Bounds::default(); @@ -851,13 +884,21 @@ impl<'tcx> ItemCtxt<'tcx> { continue; }; - let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { - ty - } else if matches!(filter, PredicateFilter::All) { - self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty) - } else { - continue; - }; + match filter { + _ if predicate.is_param_bound(param_def_id.to_def_id()) => { + // Ok + } + PredicateFilter::All => { + // Ok + } + PredicateFilter::SelfOnly + | PredicateFilter::SelfTraitThatDefines(_) + | PredicateFilter::SelfConstIfConst + | PredicateFilter::SelfAndAssociatedTypeBounds => continue, + PredicateFilter::ConstIfConst => unreachable!(), + } + + let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty); let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); self.lowerer().lower_bounds( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 8cc475b536d17..85ba88333f9ef 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -152,9 +152,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 'tcx: 'hir, { for hir_bound in hir_bounds { - // In order to avoid cycles, when we're lowering `SelfThatDefines`, + // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. - if let PredicateFilter::SelfThatDefines(assoc_name) = predicate_filter { + if let PredicateFilter::SelfTraitThatDefines(assoc_name) = predicate_filter { if let Some(trait_ref) = hir_bound.trait_ref() && let Some(trait_did) = trait_ref.trait_def_id() && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) @@ -389,7 +389,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match predicate_filter { PredicateFilter::All | PredicateFilter::SelfOnly - | PredicateFilter::SelfThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { bounds.push_projection_bound( tcx, @@ -400,6 +399,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.span, ); } + // SelfTraitThatDefines is only interested in trait predicates. + PredicateFilter::SelfTraitThatDefines(_) => {} // `ConstIfConst` is only interested in `~const` bounds. PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} } @@ -426,7 +427,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } PredicateFilter::SelfOnly - | PredicateFilter::SelfThatDefines(_) + | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfConstIfConst => {} } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 848813ffcb8a7..fb23ad1b24894 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -76,7 +76,7 @@ pub enum PredicateFilter { /// Only traits that reference `Self: ..` and define an associated type /// with the given ident are implied by the trait. This mode exists to /// side-step query cycles when lowering associated types. - SelfThatDefines(Ident), + SelfTraitThatDefines(Ident), /// Only traits that reference `Self: ..` and their associated type bounds. /// For example, given `Self: Tr`, this would expand to `Self: Tr` @@ -730,9 +730,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } match predicate_filter { + // This is only concerned with trait predicates. + PredicateFilter::SelfTraitThatDefines(..) => { + bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); + } PredicateFilter::All | PredicateFilter::SelfOnly - | PredicateFilter::SelfThatDefines(..) | PredicateFilter::SelfAndAssociatedTypeBounds => { debug!(?poly_trait_ref); bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);