@@ -310,8 +310,17 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
310
310
}
311
311
}
312
312
313
- fn get_type_parameter_bounds ( & self , span : Span , def_id : DefId ) -> ty:: GenericPredicates < ' tcx > {
314
- self . tcx . at ( span) . type_param_predicates ( ( self . item_def_id , def_id. expect_local ( ) ) )
313
+ fn get_type_parameter_bounds (
314
+ & self ,
315
+ span : Span ,
316
+ def_id : DefId ,
317
+ assoc_name : Ident ,
318
+ ) -> ty:: GenericPredicates < ' tcx > {
319
+ self . tcx . at ( span) . type_param_predicates ( (
320
+ self . item_def_id ,
321
+ def_id. expect_local ( ) ,
322
+ assoc_name,
323
+ ) )
315
324
}
316
325
317
326
fn re_infer ( & self , _: Option < & ty:: GenericParamDef > , _: Span ) -> Option < ty:: Region < ' tcx > > {
@@ -492,7 +501,7 @@ fn get_new_lifetime_name<'tcx>(
492
501
/// `X: Foo` where `X` is the type parameter `def_id`.
493
502
fn type_param_predicates (
494
503
tcx : TyCtxt < ' _ > ,
495
- ( item_def_id, def_id) : ( DefId , LocalDefId ) ,
504
+ ( item_def_id, def_id, assoc_name ) : ( DefId , LocalDefId , Ident ) ,
496
505
) -> ty:: GenericPredicates < ' _ > {
497
506
use rustc_hir:: * ;
498
507
@@ -517,7 +526,7 @@ fn type_param_predicates(
517
526
let mut result = parent
518
527
. map ( |parent| {
519
528
let icx = ItemCtxt :: new ( tcx, parent) ;
520
- icx. get_type_parameter_bounds ( DUMMY_SP , def_id. to_def_id ( ) )
529
+ icx. get_type_parameter_bounds ( DUMMY_SP , def_id. to_def_id ( ) , assoc_name )
521
530
} )
522
531
. unwrap_or_default ( ) ;
523
532
let mut extend = None ;
@@ -560,12 +569,18 @@ fn type_param_predicates(
560
569
561
570
let icx = ItemCtxt :: new ( tcx, item_def_id) ;
562
571
let extra_predicates = extend. into_iter ( ) . chain (
563
- icx. type_parameter_bounds_in_generics ( ast_generics, param_id, ty, OnlySelfBounds ( true ) )
564
- . into_iter ( )
565
- . filter ( |( predicate, _) | match predicate. skip_binders ( ) {
566
- ty:: PredicateAtom :: Trait ( data, _) => data. self_ty ( ) . is_param ( index) ,
567
- _ => false ,
568
- } ) ,
572
+ icx. type_parameter_bounds_in_generics (
573
+ ast_generics,
574
+ param_id,
575
+ ty,
576
+ OnlySelfBounds ( true ) ,
577
+ Some ( assoc_name) ,
578
+ )
579
+ . into_iter ( )
580
+ . filter ( |( predicate, _) | match predicate. skip_binders ( ) {
581
+ ty:: PredicateAtom :: Trait ( data, _) => data. self_ty ( ) . is_param ( index) ,
582
+ _ => false ,
583
+ } ) ,
569
584
) ;
570
585
result. predicates =
571
586
tcx. arena . alloc_from_iter ( result. predicates . iter ( ) . copied ( ) . chain ( extra_predicates) ) ;
@@ -583,6 +598,7 @@ impl ItemCtxt<'tcx> {
583
598
param_id : hir:: HirId ,
584
599
ty : Ty < ' tcx > ,
585
600
only_self_bounds : OnlySelfBounds ,
601
+ assoc_name : Option < Ident > ,
586
602
) -> Vec < ( ty:: Predicate < ' tcx > , Span ) > {
587
603
let constness = self . default_constness_for_trait_bounds ( ) ;
588
604
let from_ty_params = ast_generics
@@ -593,6 +609,10 @@ impl ItemCtxt<'tcx> {
593
609
_ => None ,
594
610
} )
595
611
. flat_map ( |bounds| bounds. iter ( ) )
612
+ . filter ( |b| match assoc_name {
613
+ Some ( assoc_name) => self . bound_defines_assoc_item ( b, assoc_name) ,
614
+ None => true ,
615
+ } )
596
616
. flat_map ( |b| predicates_from_bound ( self , ty, b, constness) ) ;
597
617
598
618
let from_where_clauses = ast_generics
@@ -611,12 +631,43 @@ impl ItemCtxt<'tcx> {
611
631
} else {
612
632
None
613
633
} ;
614
- bp. bounds . iter ( ) . filter_map ( move |b| bt. map ( |bt| ( bt, b) ) )
634
+ bp. bounds
635
+ . iter ( )
636
+ . filter ( |b| match assoc_name {
637
+ Some ( assoc_name) => self . bound_defines_assoc_item ( b, assoc_name) ,
638
+ None => true ,
639
+ } )
640
+ . filter_map ( move |b| bt. map ( |bt| ( bt, b) ) )
615
641
} )
616
642
. flat_map ( |( bt, b) | predicates_from_bound ( self , bt, b, constness) ) ;
617
643
618
644
from_ty_params. chain ( from_where_clauses) . collect ( )
619
645
}
646
+
647
+ fn bound_defines_assoc_item ( & self , b : & hir:: GenericBound < ' _ > , assoc_name : Ident ) -> bool {
648
+ debug ! ( "bound_defines_assoc_item(b={:?}, assoc_name={:?})" , b, assoc_name) ;
649
+
650
+ match b {
651
+ hir:: GenericBound :: Trait ( poly_trait_ref, _) => {
652
+ let trait_ref = & poly_trait_ref. trait_ref ;
653
+ let trait_did = trait_ref. trait_def_id ( ) . unwrap ( ) ;
654
+ let traits_did = super_traits_of ( self . tcx , trait_did) ;
655
+
656
+ traits_did. iter ( ) . any ( |trait_did| {
657
+ self . tcx
658
+ . associated_items ( * trait_did)
659
+ . find_by_name_and_kind (
660
+ self . tcx ,
661
+ assoc_name,
662
+ ty:: AssocKind :: Type ,
663
+ * trait_did,
664
+ )
665
+ . is_some ( )
666
+ } )
667
+ }
668
+ _ => false ,
669
+ }
670
+ }
620
671
}
621
672
622
673
/// Tests whether this is the AST for a reference to the type
@@ -1017,6 +1068,7 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi
1017
1068
item. hir_id ,
1018
1069
self_param_ty,
1019
1070
OnlySelfBounds ( !is_trait_alias) ,
1071
+ None ,
1020
1072
) ;
1021
1073
1022
1074
// Combine the two lists to form the complete set of superbounds:
@@ -1034,6 +1086,45 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi
1034
1086
ty:: GenericPredicates { parent : None , predicates : superbounds }
1035
1087
}
1036
1088
1089
+ pub fn super_traits_of ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> impl Iterator < Item = DefId > {
1090
+ let mut set = FxHashSet :: default ( ) ;
1091
+ let mut stack = vec ! [ trait_def_id] ;
1092
+ while let Some ( trait_did) = stack. pop ( ) {
1093
+ if !set. insert ( trait_did) {
1094
+ continue ;
1095
+ }
1096
+
1097
+ if trait_did. is_local ( ) {
1098
+ let trait_hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( trait_did. expect_local ( ) ) ;
1099
+
1100
+ let item = match tcx. hir ( ) . get ( trait_hir_id) {
1101
+ Node :: Item ( item) => item,
1102
+ _ => bug ! ( "super_trait_of {} is not an item" , trait_hir_id) ,
1103
+ } ;
1104
+
1105
+ let supertraits = match item. kind {
1106
+ hir:: ItemKind :: Trait ( .., ref supertraits, _) => supertraits,
1107
+ hir:: ItemKind :: TraitAlias ( _, ref supertraits) => supertraits,
1108
+ _ => span_bug ! ( item. span, "super_trait_of invoked on non-trait" ) ,
1109
+ } ;
1110
+
1111
+ for supertrait in supertraits. iter ( ) {
1112
+ let trait_ref = supertrait. trait_ref ( ) ;
1113
+ if let Some ( trait_did) = trait_ref. and_then ( |trait_ref| trait_ref. trait_def_id ( ) ) {
1114
+ stack. push ( trait_did) ;
1115
+ }
1116
+ }
1117
+ } else {
1118
+ let generic_predicates = tcx. super_predicates_of ( trait_did) ;
1119
+ for ( predicate, _) in generic_predicates. predicates {
1120
+ if let ty:: PredicateAtom :: Trait ( data, _) = predicate. skip_binders ( ) {
1121
+ stack. push ( data. def_id ( ) ) ;
1122
+ }
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+
1037
1128
fn trait_def ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> ty:: TraitDef {
1038
1129
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
1039
1130
let item = tcx. hir ( ) . expect_item ( hir_id) ;
0 commit comments