@@ -532,15 +532,20 @@ pub(super) fn explicit_predicates_of<'tcx>(
532
532
533
533
#[ derive( Copy , Clone , Debug ) ]
534
534
pub enum PredicateFilter {
535
- /// All predicates may be implied by the trait
535
+ /// All predicates may be implied by the trait.
536
536
All ,
537
537
538
- /// Only traits that reference `Self: ..` are implied by the trait
538
+ /// Only traits that reference `Self: ..` are implied by the trait.
539
539
SelfOnly ,
540
540
541
541
/// Only traits that reference `Self: ..` and define an associated type
542
- /// with the given ident are implied by the trait
542
+ /// with the given ident are implied by the trait.
543
543
SelfThatDefines ( Ident ) ,
544
+
545
+ /// Only traits that reference `Self: ..` and their associated type bounds.
546
+ /// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
547
+ /// and `<Self as Tr>::A: B`.
548
+ SelfAndAssociatedTypeBounds ,
544
549
}
545
550
546
551
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -564,11 +569,15 @@ pub(super) fn implied_predicates_of(
564
569
tcx : TyCtxt < ' _ > ,
565
570
trait_def_id : LocalDefId ,
566
571
) -> ty:: GenericPredicates < ' _ > {
567
- if tcx. is_trait_alias ( trait_def_id. to_def_id ( ) ) {
568
- implied_predicates_with_filter ( tcx, trait_def_id. to_def_id ( ) , PredicateFilter :: All )
569
- } else {
570
- tcx. super_predicates_of ( trait_def_id)
571
- }
572
+ implied_predicates_with_filter (
573
+ tcx,
574
+ trait_def_id. to_def_id ( ) ,
575
+ if tcx. is_trait_alias ( trait_def_id. to_def_id ( ) ) {
576
+ PredicateFilter :: All
577
+ } else {
578
+ PredicateFilter :: SelfAndAssociatedTypeBounds
579
+ } ,
580
+ )
572
581
}
573
582
574
583
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -601,45 +610,28 @@ pub(super) fn implied_predicates_with_filter(
601
610
let icx = ItemCtxt :: new ( tcx, trait_def_id) ;
602
611
603
612
let self_param_ty = tcx. types . self_param ;
604
- let ( superbounds, where_bounds_that_match) = match filter {
605
- PredicateFilter :: All => (
606
- // Convert the bounds that follow the colon (or equal in trait aliases)
607
- icx. astconv ( ) . compute_bounds ( self_param_ty, bounds, OnlySelfBounds ( false ) ) ,
608
- // Also include all where clause bounds
609
- icx. type_parameter_bounds_in_generics (
610
- generics,
611
- item. owner_id . def_id ,
612
- self_param_ty,
613
- OnlySelfBounds ( false ) ,
614
- None ,
615
- ) ,
616
- ) ,
617
- PredicateFilter :: SelfOnly => (
618
- // Convert the bounds that follow the colon (or equal in trait aliases)
619
- icx. astconv ( ) . compute_bounds ( self_param_ty, bounds, OnlySelfBounds ( true ) ) ,
620
- // Include where clause bounds for `Self`
621
- icx. type_parameter_bounds_in_generics (
622
- generics,
623
- item. owner_id . def_id ,
624
- self_param_ty,
625
- OnlySelfBounds ( true ) ,
626
- None ,
627
- ) ,
628
- ) ,
629
- PredicateFilter :: SelfThatDefines ( assoc_name) => (
630
- // Convert the bounds that follow the colon (or equal) that reference the associated name
631
- icx. astconv ( ) . compute_bounds_that_match_assoc_item ( self_param_ty, bounds, assoc_name) ,
632
- // Include where clause bounds for `Self` that reference the associated name
633
- icx. type_parameter_bounds_in_generics (
634
- generics,
635
- item. owner_id . def_id ,
636
- self_param_ty,
637
- OnlySelfBounds ( true ) ,
638
- Some ( assoc_name) ,
639
- ) ,
640
- ) ,
613
+ let superbounds = match filter {
614
+ // Should imply both "real" supertraits, and also associated type bounds
615
+ // from the supertraits position.
616
+ PredicateFilter :: All | PredicateFilter :: SelfAndAssociatedTypeBounds => {
617
+ icx. astconv ( ) . compute_bounds ( self_param_ty, bounds, OnlySelfBounds ( false ) )
618
+ }
619
+ // Should only imply "real" supertraits, i.e. predicates with the self type `Self`.
620
+ PredicateFilter :: SelfOnly => {
621
+ icx. astconv ( ) . compute_bounds ( self_param_ty, bounds, OnlySelfBounds ( true ) )
622
+ }
623
+ PredicateFilter :: SelfThatDefines ( assoc_name) => {
624
+ icx. astconv ( ) . compute_bounds_that_match_assoc_item ( self_param_ty, bounds, assoc_name)
625
+ }
641
626
} ;
642
627
628
+ let where_bounds_that_match = icx. type_parameter_bounds_in_generics (
629
+ generics,
630
+ item. owner_id . def_id ,
631
+ self_param_ty,
632
+ filter,
633
+ ) ;
634
+
643
635
// Combine the two lists to form the complete set of superbounds:
644
636
let implied_bounds =
645
637
& * tcx. arena . alloc_from_iter ( superbounds. clauses ( ) . chain ( where_bounds_that_match) ) ;
@@ -743,8 +735,7 @@ pub(super) fn type_param_predicates(
743
735
ast_generics,
744
736
def_id,
745
737
ty,
746
- OnlySelfBounds ( true ) ,
747
- Some ( assoc_name) ,
738
+ PredicateFilter :: SelfThatDefines ( assoc_name) ,
748
739
)
749
740
. into_iter ( )
750
741
. filter ( |( predicate, _) | match predicate. kind ( ) . skip_binder ( ) {
@@ -768,8 +759,7 @@ impl<'tcx> ItemCtxt<'tcx> {
768
759
ast_generics : & ' tcx hir:: Generics < ' tcx > ,
769
760
param_def_id : LocalDefId ,
770
761
ty : Ty < ' tcx > ,
771
- only_self_bounds : OnlySelfBounds ,
772
- assoc_name : Option < Ident > ,
762
+ filter : PredicateFilter ,
773
763
) -> Vec < ( ty:: Clause < ' tcx > , Span ) > {
774
764
let mut bounds = Bounds :: default ( ) ;
775
765
@@ -778,9 +768,23 @@ impl<'tcx> ItemCtxt<'tcx> {
778
768
continue ;
779
769
} ;
780
770
771
+ let ( only_self_bounds, assoc_name) = match filter {
772
+ PredicateFilter :: All | PredicateFilter :: SelfAndAssociatedTypeBounds => {
773
+ ( OnlySelfBounds ( false ) , None )
774
+ }
775
+ PredicateFilter :: SelfOnly => ( OnlySelfBounds ( true ) , None ) ,
776
+ PredicateFilter :: SelfThatDefines ( assoc_name) => {
777
+ ( OnlySelfBounds ( true ) , Some ( assoc_name) )
778
+ }
779
+ } ;
780
+
781
+ // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
782
+ // want to only consider predicates with `Self: ...`, but we don't want
783
+ // `OnlySelfBounds(true)` since we want to collect the nested associated
784
+ // type bound as well.
781
785
let bound_ty = if predicate. is_param_bound ( param_def_id. to_def_id ( ) ) {
782
786
ty
783
- } else if !only_self_bounds . 0 {
787
+ } else if matches ! ( filter , PredicateFilter :: All ) {
784
788
self . to_ty ( predicate. bounded_ty )
785
789
} else {
786
790
continue ;
0 commit comments