@@ -53,7 +53,7 @@ use tracing::debug;
5353use triomphe:: { Arc , ThinArc } ;
5454
5555use crate :: {
56- FnAbi , ImplTraitId , TyLoweringDiagnostic , TyLoweringDiagnosticKind ,
56+ FnAbi , ImplTraitId , TyLoweringDiagnostic , TyLoweringDiagnosticKind , all_super_traits ,
5757 consteval:: intern_const_ref,
5858 db:: { HirDatabase , InternedOpaqueTyId } ,
5959 generics:: { Generics , generics, trait_self_param_idx} ,
@@ -1619,11 +1619,16 @@ pub(crate) fn field_types_with_diagnostics_query<'db>(
16191619 ( res, create_diagnostics ( ctx. diagnostics ) )
16201620}
16211621
1622+ /// Predicates for `param_id` of the form `P: SomeTrait`. If
1623+ /// `assoc_name` is provided, only return predicates referencing traits
1624+ /// that have an associated type of that name.
1625+ ///
16221626/// This query exists only to be used when resolving short-hand associated types
16231627/// like `T::Item`.
16241628///
16251629/// See the analogous query in rustc and its comment:
16261630/// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46>
1631+ ///
16271632/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
16281633/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
16291634/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
@@ -1647,7 +1652,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16471652 ) ;
16481653
16491654 // we have to filter out all other predicates *first*, before attempting to lower them
1650- let predicate = |pred : & _ , ctx : & mut TyLoweringContext < ' _ , ' _ > | match pred {
1655+ let has_relevant_bound = |pred : & _ , ctx : & mut TyLoweringContext < ' _ , ' _ > | match pred {
16511656 WherePredicate :: ForLifetime { target, bound, .. }
16521657 | WherePredicate :: TypeBound { target, bound, .. } => {
16531658 let invalid_target = { ctx. lower_ty_only_param ( * target) != Some ( param_id) } ;
@@ -1695,11 +1700,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16951700 return false ;
16961701 } ;
16971702
1698- rustc_type_ir:: elaborate:: supertrait_def_ids ( interner, tr. into ( ) ) . any ( |tr| {
1699- tr. 0 . trait_items ( db) . items . iter ( ) . any ( |( name, item) | {
1700- matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name
1701- } )
1702- } )
1703+ trait_or_supertrait_has_assoc_type ( db, tr, assoc_name)
17031704 }
17041705 TypeBound :: Use ( _) | TypeBound :: Lifetime ( _) | TypeBound :: Error => false ,
17051706 }
@@ -1712,7 +1713,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
17121713 {
17131714 ctx. store = maybe_parent_generics. store ( ) ;
17141715 for pred in maybe_parent_generics. where_predicates ( ) {
1715- if predicate ( pred, & mut ctx) {
1716+ if has_relevant_bound ( pred, & mut ctx) {
17161717 predicates. extend (
17171718 ctx. lower_where_predicate (
17181719 pred,
@@ -1752,6 +1753,31 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
17521753 StoredEarlyBinder :: bind ( Clauses :: empty ( DbInterner :: new_no_crate ( db) ) . store ( ) )
17531754}
17541755
1756+ /// Check if this trait or any of its supertraits define an associated
1757+ /// type with the given name.
1758+ fn trait_or_supertrait_has_assoc_type (
1759+ db : & dyn HirDatabase ,
1760+ tr : TraitId ,
1761+ assoc_name : & Name ,
1762+ ) -> bool {
1763+ let mut trait_and_supertraits = vec ! [ tr] ;
1764+ trait_and_supertraits. extend ( & all_super_traits ( db, tr) ) ;
1765+
1766+ for trait_id in trait_and_supertraits {
1767+ // Check if this trait has the associated type.
1768+ if trait_id
1769+ . trait_items ( db)
1770+ . items
1771+ . iter ( )
1772+ . any ( |( name, item) | matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name)
1773+ {
1774+ return true ;
1775+ }
1776+ }
1777+
1778+ false
1779+ }
1780+
17551781#[ inline]
17561782pub ( crate ) fn type_alias_bounds < ' db > (
17571783 db : & ' db dyn HirDatabase ,
0 commit comments