@@ -2,7 +2,7 @@ use smallvec::smallvec;
22
33use crate :: infer:: outlives:: components:: { push_outlives_components, Component } ;
44use crate :: traits:: { self , Obligation , PredicateObligation } ;
5- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
5+ use rustc_data_structures:: fx:: FxHashSet ;
66use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt } ;
77use rustc_span:: symbol:: Ident ;
88use rustc_span:: Span ;
@@ -76,7 +76,13 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
7676pub struct Elaborator < ' tcx , O > {
7777 stack : Vec < O > ,
7878 visited : PredicateSet < ' tcx > ,
79- only_self : bool ,
79+ mode : Filter ,
80+ }
81+
82+ enum Filter {
83+ All ,
84+ OnlySelf ,
85+ OnlySelfThatDefines ( Ident ) ,
8086}
8187
8288/// Describes how to elaborate an obligation into a sub-obligation.
@@ -224,7 +230,7 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
224230 obligations : impl IntoIterator < Item = O > ,
225231) -> Elaborator < ' tcx , O > {
226232 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 } ;
228234 elaborator. extend_deduped ( obligations) ;
229235 elaborator
230236}
@@ -242,7 +248,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
242248 /// Filter to only the supertraits of trait predicates, i.e. only the predicates
243249 /// that have `Self` as their self type, instead of all implied predicates.
244250 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) ;
246258 self
247259 }
248260
@@ -257,10 +269,12 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
257269 return ;
258270 }
259271 // 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+ }
264278 } ;
265279
266280 let obligations =
@@ -416,7 +430,7 @@ pub fn supertraits<'tcx>(
416430pub fn transitive_bounds < ' tcx > (
417431 tcx : TyCtxt < ' tcx > ,
418432 trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
419- ) -> impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > {
433+ ) -> FilterToTraits < Elaborator < ' tcx , ty:: Predicate < ' tcx > > > {
420434 elaborate ( tcx, trait_refs. map ( |trait_ref| trait_ref. to_predicate ( tcx) ) )
421435 . filter_only_self ( )
422436 . filter_to_traits ( )
@@ -429,31 +443,12 @@ pub fn transitive_bounds<'tcx>(
429443/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
430444pub fn transitive_bounds_that_define_assoc_item < ' tcx > (
431445 tcx : TyCtxt < ' tcx > ,
432- bounds : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
446+ trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
433447 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 ( )
457452}
458453
459454///////////////////////////////////////////////////////////////////////////
0 commit comments