@@ -2,7 +2,7 @@ use smallvec::smallvec;
2
2
3
3
use crate :: infer:: outlives:: components:: { push_outlives_components, Component } ;
4
4
use crate :: traits:: { self , Obligation , PredicateObligation } ;
5
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
5
+ use rustc_data_structures:: fx:: FxHashSet ;
6
6
use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt } ;
7
7
use rustc_span:: symbol:: Ident ;
8
8
use rustc_span:: Span ;
@@ -76,7 +76,13 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
76
76
pub struct Elaborator < ' tcx , O > {
77
77
stack : Vec < O > ,
78
78
visited : PredicateSet < ' tcx > ,
79
- only_self : bool ,
79
+ mode : Filter ,
80
+ }
81
+
82
+ enum Filter {
83
+ All ,
84
+ OnlySelf ,
85
+ OnlySelfThatDefines ( Ident ) ,
80
86
}
81
87
82
88
/// Describes how to elaborate an obligation into a sub-obligation.
@@ -224,7 +230,7 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
224
230
obligations : impl IntoIterator < Item = O > ,
225
231
) -> Elaborator < ' tcx , O > {
226
232
let mut elaborator =
227
- Elaborator { stack : Vec :: new ( ) , visited : PredicateSet :: new ( tcx) , only_self : false } ;
233
+ Elaborator { stack : Vec :: new ( ) , visited : PredicateSet :: new ( tcx) , mode : Filter :: All } ;
228
234
elaborator. extend_deduped ( obligations) ;
229
235
elaborator
230
236
}
@@ -242,7 +248,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
242
248
/// Filter to only the supertraits of trait predicates, i.e. only the predicates
243
249
/// that have `Self` as their self type, instead of all implied predicates.
244
250
pub fn filter_only_self ( mut self ) -> Self {
245
- self . only_self = true ;
251
+ self . mode = Filter :: OnlySelf ;
252
+ self
253
+ }
254
+
255
+ /// Filter to only the supertraits of trait predicates that define the assoc_ty.
256
+ pub fn filter_only_self_that_defines ( mut self , assoc_ty : Ident ) -> Self {
257
+ self . mode = Filter :: OnlySelfThatDefines ( assoc_ty) ;
246
258
self
247
259
}
248
260
@@ -257,10 +269,12 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
257
269
return ;
258
270
}
259
271
// Get predicates implied by the trait, or only super predicates if we only care about self predicates.
260
- let predicates = if self . only_self {
261
- tcx. super_predicates_of ( data. def_id ( ) )
262
- } else {
263
- tcx. implied_predicates_of ( data. def_id ( ) )
272
+ let predicates = match self . mode {
273
+ Filter :: All => tcx. implied_predicates_of ( data. def_id ( ) ) ,
274
+ Filter :: OnlySelf => tcx. super_predicates_of ( data. def_id ( ) ) ,
275
+ Filter :: OnlySelfThatDefines ( ident) => {
276
+ tcx. super_predicates_that_define_assoc_item ( ( data. def_id ( ) , ident) )
277
+ }
264
278
} ;
265
279
266
280
let obligations =
@@ -409,14 +423,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> {
409
423
pub fn supertraits < ' tcx > (
410
424
tcx : TyCtxt < ' tcx > ,
411
425
trait_ref : ty:: PolyTraitRef < ' tcx > ,
412
- ) -> impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > {
426
+ ) -> FilterToTraits < Elaborator < ' tcx , ty:: Predicate < ' tcx > > > {
413
427
elaborate ( tcx, [ trait_ref. to_predicate ( tcx) ] ) . filter_only_self ( ) . filter_to_traits ( )
414
428
}
415
429
416
430
pub fn transitive_bounds < ' tcx > (
417
431
tcx : TyCtxt < ' tcx > ,
418
432
trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
419
- ) -> impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > {
433
+ ) -> FilterToTraits < Elaborator < ' tcx , ty:: Predicate < ' tcx > > > {
420
434
elaborate ( tcx, trait_refs. map ( |trait_ref| trait_ref. to_predicate ( tcx) ) )
421
435
. filter_only_self ( )
422
436
. filter_to_traits ( )
@@ -429,31 +443,12 @@ pub fn transitive_bounds<'tcx>(
429
443
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
430
444
pub fn transitive_bounds_that_define_assoc_item < ' tcx > (
431
445
tcx : TyCtxt < ' tcx > ,
432
- bounds : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
446
+ trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
433
447
assoc_name : Ident ,
434
- ) -> impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > {
435
- let mut stack: Vec < _ > = bounds. collect ( ) ;
436
- let mut visited = FxIndexSet :: default ( ) ;
437
-
438
- std:: iter:: from_fn ( move || {
439
- while let Some ( trait_ref) = stack. pop ( ) {
440
- let anon_trait_ref = tcx. anonymize_bound_vars ( trait_ref) ;
441
- if visited. insert ( anon_trait_ref) {
442
- let super_predicates =
443
- tcx. super_predicates_that_define_assoc_item ( ( trait_ref. def_id ( ) , assoc_name) ) ;
444
- for ( super_predicate, _) in super_predicates. predicates {
445
- let subst_predicate = super_predicate. subst_supertrait ( tcx, & trait_ref) ;
446
- if let Some ( binder) = subst_predicate. as_trait_clause ( ) {
447
- stack. push ( binder. map_bound ( |t| t. trait_ref ) ) ;
448
- }
449
- }
450
-
451
- return Some ( trait_ref) ;
452
- }
453
- }
454
-
455
- return None ;
456
- } )
448
+ ) -> FilterToTraits < Elaborator < ' tcx , ty:: Predicate < ' tcx > > > {
449
+ elaborate ( tcx, trait_refs. map ( |trait_ref| trait_ref. to_predicate ( tcx) ) )
450
+ . filter_only_self_that_defines ( assoc_name)
451
+ . filter_to_traits ( )
457
452
}
458
453
459
454
///////////////////////////////////////////////////////////////////////////
0 commit comments