@@ -1649,11 +1649,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16491649 return false ;
16501650 } ;
16511651
1652- rustc_type_ir:: elaborate:: supertrait_def_ids ( interner, tr. into ( ) ) . any ( |tr| {
1653- tr. 0 . trait_items ( db) . items . iter ( ) . any ( |( name, item) | {
1654- matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name
1655- } )
1656- } )
1652+ trait_or_supertrait_has_assoc_type ( db, tr, assoc_name)
16571653 }
16581654 TypeBound :: Use ( _) | TypeBound :: Lifetime ( _) | TypeBound :: Error => false ,
16591655 }
@@ -1703,6 +1699,45 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
17031699 StoredEarlyBinder :: bind ( Clauses :: empty ( DbInterner :: new_no_crate ( db) ) . store ( ) )
17041700}
17051701
1702+ /// Check if a trait or any of its supertraits define an associated
1703+ /// type with the given name.
1704+ fn trait_or_supertrait_has_assoc_type ( db : & dyn HirDatabase , tr : TraitId , assoc_name : & Name ) -> bool {
1705+ let mut visited = FxHashSet :: default ( ) ;
1706+ let mut stack = vec ! [ tr] ;
1707+
1708+ // In valid Rust code, there should never be a cycle. However, the
1709+ // user may write erroneous code that contains a cycle, so be
1710+ // defensive against that.
1711+ while let Some ( trait_id) = stack. pop ( ) {
1712+ if !visited. insert ( trait_id) {
1713+ continue ;
1714+ }
1715+
1716+ // Check if this trait has the associated type.
1717+ if trait_id. trait_items ( db) . items . iter ( ) . any ( |( name, item) | {
1718+ matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name
1719+ } ) {
1720+ return true ;
1721+ }
1722+
1723+ // Walk supertraits.
1724+ let params = db. generic_params ( trait_id. into ( ) ) ;
1725+ if let Some ( self_param) = params. trait_self_param ( ) {
1726+ let self_param_id =
1727+ TypeOrConstParamId { parent : trait_id. into ( ) , local_id : self_param } ;
1728+
1729+ let predicates = generic_predicates_for_param ( db, trait_id. into ( ) , self_param_id, None ) ;
1730+ for pred in predicates. get ( ) . iter_identity ( ) {
1731+ if let rustc_type_ir:: ClauseKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( ) {
1732+ stack. push ( trait_pred. trait_ref . def_id . 0 ) ;
1733+ }
1734+ }
1735+ }
1736+ }
1737+
1738+ false
1739+ }
1740+
17061741#[ inline]
17071742pub ( crate ) fn type_alias_bounds < ' db > (
17081743 db : & ' db dyn HirDatabase ,
0 commit comments