@@ -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} ,
@@ -1624,11 +1624,16 @@ pub(crate) fn field_types_with_diagnostics_query<'db>(
16241624 ( res, create_diagnostics ( ctx. diagnostics ) )
16251625}
16261626
1627+ /// Predicates for `param_id` of the form `P: SomeTrait`. If
1628+ /// `assoc_name` is provided, only return predicates referencing traits
1629+ /// that have an associated type of that name.
1630+ ///
16271631/// This query exists only to be used when resolving short-hand associated types
16281632/// like `T::Item`.
16291633///
16301634/// See the analogous query in rustc and its comment:
16311635/// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46>
1636+ ///
16321637/// This is a query mostly to handle cycles somewhat gracefully; e.g. the
16331638/// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but
16341639/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
@@ -1652,7 +1657,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
16521657 ) ;
16531658
16541659 // we have to filter out all other predicates *first*, before attempting to lower them
1655- let predicate = |pred : & _ , ctx : & mut TyLoweringContext < ' _ , ' _ > | match pred {
1660+ let has_relevant_bound = |pred : & _ , ctx : & mut TyLoweringContext < ' _ , ' _ > | match pred {
16561661 WherePredicate :: ForLifetime { target, bound, .. }
16571662 | WherePredicate :: TypeBound { target, bound, .. } => {
16581663 let invalid_target = { ctx. lower_ty_only_param ( * target) != Some ( param_id) } ;
@@ -1700,11 +1705,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
17001705 return false ;
17011706 } ;
17021707
1703- rustc_type_ir:: elaborate:: supertrait_def_ids ( interner, tr. into ( ) ) . any ( |tr| {
1704- tr. 0 . trait_items ( db) . items . iter ( ) . any ( |( name, item) | {
1705- matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name
1706- } )
1707- } )
1708+ trait_or_supertrait_has_assoc_type ( db, tr, assoc_name)
17081709 }
17091710 TypeBound :: Use ( _) | TypeBound :: Lifetime ( _) | TypeBound :: Error => false ,
17101711 }
@@ -1717,7 +1718,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
17171718 {
17181719 ctx. store = maybe_parent_generics. store ( ) ;
17191720 for pred in maybe_parent_generics. where_predicates ( ) {
1720- if predicate ( pred, & mut ctx) {
1721+ if has_relevant_bound ( pred, & mut ctx) {
17211722 predicates. extend (
17221723 ctx. lower_where_predicate (
17231724 pred,
@@ -1757,6 +1758,27 @@ pub(crate) fn generic_predicates_for_param_cycle_result(
17571758 StoredEarlyBinder :: bind ( Clauses :: empty ( DbInterner :: new_no_crate ( db) ) . store ( ) )
17581759}
17591760
1761+ /// Check if this trait or any of its supertraits define an associated
1762+ /// type with the given name.
1763+ fn trait_or_supertrait_has_assoc_type (
1764+ db : & dyn HirDatabase ,
1765+ tr : TraitId ,
1766+ assoc_name : & Name ,
1767+ ) -> bool {
1768+ for trait_id in all_super_traits ( db, tr) {
1769+ if trait_id
1770+ . trait_items ( db)
1771+ . items
1772+ . iter ( )
1773+ . any ( |( name, item) | matches ! ( item, AssocItemId :: TypeAliasId ( _) ) && name == assoc_name)
1774+ {
1775+ return true ;
1776+ }
1777+ }
1778+
1779+ false
1780+ }
1781+
17601782#[ inline]
17611783pub ( crate ) fn type_alias_bounds < ' db > (
17621784 db : & ' db dyn HirDatabase ,
0 commit comments