@@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
125125 // on a trait we need to add in the supertrait bounds and bounds found on
126126 // associated types.
127127 if let Some ( _trait_ref) = is_trait {
128- predicates. extend ( tcx. super_predicates_of ( def_id) . predicates . iter ( ) . cloned ( ) ) ;
128+ predicates. extend ( tcx. implied_predicates_of ( def_id) . predicates . iter ( ) . cloned ( ) ) ;
129129 }
130130
131131 // In default impls, we can assume that the self type implements
@@ -534,31 +534,62 @@ pub(super) fn explicit_predicates_of<'tcx>(
534534 }
535535}
536536
537+ #[ derive( Copy , Clone , Debug ) ]
538+ pub enum PredicateFilter {
539+ /// All predicates may be implied by the trait
540+ All ,
541+
542+ /// Only traits that reference `Self: ..` are implied by the trait
543+ SelfOnly ,
544+
545+ /// Only traits that reference `Self: ..` and define an associated type
546+ /// with the given ident are implied by the trait
547+ SelfThatDefines ( Ident ) ,
548+ }
549+
537550/// Ensures that the super-predicates of the trait with a `DefId`
538551/// of `trait_def_id` are converted and stored. This also ensures that
539552/// the transitive super-predicates are converted.
540553pub ( super ) fn super_predicates_of (
541554 tcx : TyCtxt < ' _ > ,
542555 trait_def_id : LocalDefId ,
543556) -> ty:: GenericPredicates < ' _ > {
544- tcx. super_predicates_that_define_assoc_type ( ( trait_def_id. to_def_id ( ) , None ) )
557+ implied_predicates_with_filter ( tcx, trait_def_id. to_def_id ( ) , PredicateFilter :: SelfOnly )
558+ }
559+
560+ pub ( super ) fn super_predicates_that_define_assoc_type (
561+ tcx : TyCtxt < ' _ > ,
562+ ( trait_def_id, assoc_name) : ( DefId , Ident ) ,
563+ ) -> ty:: GenericPredicates < ' _ > {
564+ implied_predicates_with_filter ( tcx, trait_def_id, PredicateFilter :: SelfThatDefines ( assoc_name) )
565+ }
566+
567+ pub ( super ) fn implied_predicates_of (
568+ tcx : TyCtxt < ' _ > ,
569+ trait_def_id : LocalDefId ,
570+ ) -> ty:: GenericPredicates < ' _ > {
571+ if tcx. is_trait_alias ( trait_def_id. to_def_id ( ) ) {
572+ implied_predicates_with_filter ( tcx, trait_def_id. to_def_id ( ) , PredicateFilter :: All )
573+ } else {
574+ tcx. super_predicates_of ( trait_def_id)
575+ }
545576}
546577
547578/// Ensures that the super-predicates of the trait with a `DefId`
548579/// of `trait_def_id` are converted and stored. This also ensures that
549580/// the transitive super-predicates are converted.
550- pub ( super ) fn super_predicates_that_define_assoc_type (
581+ pub ( super ) fn implied_predicates_with_filter (
551582 tcx : TyCtxt < ' _ > ,
552- ( trait_def_id, assoc_name) : ( DefId , Option < Ident > ) ,
583+ trait_def_id : DefId ,
584+ filter : PredicateFilter ,
553585) -> ty:: GenericPredicates < ' _ > {
554586 let Some ( trait_def_id) = trait_def_id. as_local ( ) else {
555587 // if `assoc_name` is None, then the query should've been redirected to an
556588 // external provider
557- assert ! ( assoc_name . is_some ( ) ) ;
589+ assert ! ( matches! ( filter , PredicateFilter :: SelfThatDefines ( _ ) ) ) ;
558590 return tcx. super_predicates_of ( trait_def_id) ;
559591 } ;
560592
561- debug ! ( "local trait" ) ;
562593 let trait_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( trait_def_id) ;
563594
564595 let Node :: Item ( item) = tcx. hir ( ) . get ( trait_hir_id) else {
@@ -573,48 +604,66 @@ pub(super) fn super_predicates_that_define_assoc_type(
573604
574605 let icx = ItemCtxt :: new ( tcx, trait_def_id) ;
575606
576- // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
577607 let self_param_ty = tcx. types . self_param ;
578- let superbounds1 = if let Some ( assoc_name) = assoc_name {
579- icx. astconv ( ) . compute_bounds_that_match_assoc_type ( self_param_ty, bounds, assoc_name)
580- } else {
581- icx. astconv ( ) . compute_bounds ( self_param_ty, bounds)
608+ let ( superbounds, where_bounds_that_match) = match filter {
609+ PredicateFilter :: All => (
610+ // Convert the bounds that follow the colon (or equal in trait aliases)
611+ icx. astconv ( ) . compute_bounds ( self_param_ty, bounds) ,
612+ // Also include all where clause bounds
613+ icx. type_parameter_bounds_in_generics (
614+ generics,
615+ item. owner_id . def_id ,
616+ self_param_ty,
617+ OnlySelfBounds ( false ) ,
618+ None ,
619+ ) ,
620+ ) ,
621+ PredicateFilter :: SelfOnly => (
622+ // Convert the bounds that follow the colon (or equal in trait aliases)
623+ icx. astconv ( ) . compute_bounds ( self_param_ty, bounds) ,
624+ // Include where clause bounds for `Self`
625+ icx. type_parameter_bounds_in_generics (
626+ generics,
627+ item. owner_id . def_id ,
628+ self_param_ty,
629+ OnlySelfBounds ( true ) ,
630+ None ,
631+ ) ,
632+ ) ,
633+ PredicateFilter :: SelfThatDefines ( assoc_name) => (
634+ // Convert the bounds that follow the colon (or equal) that reference the associated name
635+ icx. astconv ( ) . compute_bounds_that_match_assoc_type ( self_param_ty, bounds, assoc_name) ,
636+ // Include where clause bounds for `Self` that reference the associated name
637+ icx. type_parameter_bounds_in_generics (
638+ generics,
639+ item. owner_id . def_id ,
640+ self_param_ty,
641+ OnlySelfBounds ( true ) ,
642+ Some ( assoc_name) ,
643+ ) ,
644+ ) ,
582645 } ;
583646
584- let superbounds1 = superbounds1. predicates ( ) ;
585-
586- // Convert any explicit superbounds in the where-clause,
587- // e.g., `trait Foo where Self: Bar`.
588- // In the case of trait aliases, however, we include all bounds in the where-clause,
589- // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
590- // as one of its "superpredicates".
591- let is_trait_alias = tcx. is_trait_alias ( trait_def_id. to_def_id ( ) ) ;
592- let superbounds2 = icx. type_parameter_bounds_in_generics (
593- generics,
594- item. owner_id . def_id ,
595- self_param_ty,
596- OnlySelfBounds ( !is_trait_alias) ,
597- assoc_name,
598- ) ;
599-
600647 // Combine the two lists to form the complete set of superbounds:
601- let superbounds = & * tcx. arena . alloc_from_iter ( superbounds1. into_iter ( ) . chain ( superbounds2) ) ;
602- debug ! ( ?superbounds) ;
648+ let implied_bounds = & * tcx
649+ . arena
650+ . alloc_from_iter ( superbounds. predicates ( ) . into_iter ( ) . chain ( where_bounds_that_match) ) ;
651+ debug ! ( ?implied_bounds) ;
603652
604653 // Now require that immediate supertraits are converted,
605654 // which will, in turn, reach indirect supertraits.
606- if assoc_name . is_none ( ) {
655+ if matches ! ( filter , PredicateFilter :: SelfOnly ) {
607656 // Now require that immediate supertraits are converted,
608657 // which will, in turn, reach indirect supertraits.
609- for & ( pred, span) in superbounds {
658+ for & ( pred, span) in implied_bounds {
610659 debug ! ( "superbound: {:?}" , pred) ;
611660 if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( bound) ) = pred. kind ( ) . skip_binder ( ) {
612661 tcx. at ( span) . super_predicates_of ( bound. def_id ( ) ) ;
613662 }
614663 }
615664 }
616665
617- ty:: GenericPredicates { parent : None , predicates : superbounds }
666+ ty:: GenericPredicates { parent : None , predicates : implied_bounds }
618667}
619668
620669/// Returns the predicates defined on `item_def_id` of the form
0 commit comments