@@ -3,7 +3,7 @@ use smallvec::smallvec;
33use crate :: infer:: outlives:: components:: { push_outlives_components, Component } ;
44use crate :: traits:: { Obligation , ObligationCause , PredicateObligation } ;
55use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
6- use rustc_middle:: ty:: { self , ToPredicate , TyCtxt } ;
6+ use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt } ;
77use rustc_span:: symbol:: Ident ;
88use rustc_span:: Span ;
99
@@ -132,8 +132,11 @@ fn predicate_obligation<'tcx>(
132132}
133133
134134impl < ' tcx > Elaborator < ' tcx > {
135- pub fn filter_to_traits ( self ) -> FilterToTraits < Self > {
136- FilterToTraits :: new ( self )
135+ pub fn filter_to_traits (
136+ self ,
137+ filter_self_ty : Option < ty:: Binder < ' tcx , Ty < ' tcx > > > ,
138+ ) -> FilterToTraits < ' tcx , Self > {
139+ FilterToTraits :: new ( self , filter_self_ty)
137140 }
138141
139142 fn elaborate ( & mut self , obligation : & PredicateObligation < ' tcx > ) {
@@ -312,20 +315,20 @@ impl<'tcx> Iterator for Elaborator<'tcx> {
312315// Supertrait iterator
313316///////////////////////////////////////////////////////////////////////////
314317
315- pub type Supertraits < ' tcx > = FilterToTraits < Elaborator < ' tcx > > ;
318+ pub type Supertraits < ' tcx > = FilterToTraits < ' tcx , Elaborator < ' tcx > > ;
316319
317320pub fn supertraits < ' tcx > (
318321 tcx : TyCtxt < ' tcx > ,
319322 trait_ref : ty:: PolyTraitRef < ' tcx > ,
320323) -> Supertraits < ' tcx > {
321- elaborate_trait_ref ( tcx, trait_ref) . filter_to_traits ( )
324+ elaborate_trait_ref ( tcx, trait_ref) . filter_to_traits ( Some ( trait_ref . self_ty ( ) ) )
322325}
323326
324327pub fn transitive_bounds < ' tcx > (
325328 tcx : TyCtxt < ' tcx > ,
326329 bounds : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
327330) -> Supertraits < ' tcx > {
328- elaborate_trait_refs ( tcx, bounds) . filter_to_traits ( )
331+ elaborate_trait_refs ( tcx, bounds) . filter_to_traits ( None )
329332}
330333
331334/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
@@ -370,22 +373,29 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
370373
371374/// A filter around an iterator of predicates that makes it yield up
372375/// just trait references.
373- pub struct FilterToTraits < I > {
376+ pub struct FilterToTraits < ' tcx , I > {
374377 base_iterator : I ,
378+ filter_self_ty : Option < ty:: Binder < ' tcx , Ty < ' tcx > > > ,
375379}
376380
377- impl < I > FilterToTraits < I > {
378- fn new ( base : I ) -> FilterToTraits < I > {
379- FilterToTraits { base_iterator : base }
381+ impl < ' tcx , I > FilterToTraits < ' tcx , I > {
382+ fn new ( base : I , filter_self_ty : Option < ty :: Binder < ' tcx , Ty < ' tcx > > > ) -> FilterToTraits < ' tcx , I > {
383+ FilterToTraits { base_iterator : base, filter_self_ty }
380384 }
381385}
382386
383- impl < ' tcx , I : Iterator < Item = PredicateObligation < ' tcx > > > Iterator for FilterToTraits < I > {
387+ impl < ' tcx , I : Iterator < Item = PredicateObligation < ' tcx > > > Iterator for FilterToTraits < ' tcx , I > {
384388 type Item = ty:: PolyTraitRef < ' tcx > ;
385389
386390 fn next ( & mut self ) -> Option < ty:: PolyTraitRef < ' tcx > > {
387391 while let Some ( obligation) = self . base_iterator . next ( ) {
388- if let Some ( data) = obligation. predicate . to_opt_poly_trait_pred ( ) {
392+ if let Some ( data) = obligation. predicate . to_opt_poly_trait_pred ( )
393+ // A note on binders: Elaboration means that the output predicates
394+ // may have more bound variables than the inputs. However, since we
395+ // only append variables to the bound vars list, it is fine to
396+ // compare self types outside of the binders.
397+ && self . filter_self_ty . map_or ( true , |filter_self_ty| filter_self_ty. skip_binder ( ) == data. skip_binder ( ) . self_ty ( ) )
398+ {
389399 return Some ( data. map_bound ( |t| t. trait_ref ) ) ;
390400 }
391401 }
0 commit comments