@@ -56,6 +56,7 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
5656 }
5757
5858 fn contains ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
59+ // See the `insert` method for why we use `anonymize_predicate` here.
5960 self . set . contains ( & anonymize_predicate ( self . tcx , pred) )
6061 }
6162
@@ -74,13 +75,14 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
7475 }
7576
7677 fn remove ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
78+ // See the `insert` method for why we use `anonymize_predicate` here.
7779 self . set . remove ( & anonymize_predicate ( self . tcx , pred) )
7880 }
7981}
8082
8183impl < ' a , ' gcx , ' tcx , T : AsRef < ty:: Predicate < ' tcx > > > Extend < T > for PredicateSet < ' a , ' gcx , ' tcx > {
8284 fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
83- for pred in iter. into_iter ( ) {
85+ for pred in iter {
8486 self . insert ( pred. as_ref ( ) ) ;
8587 }
8688 }
@@ -289,30 +291,33 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
289291/// `trait Foo = Bar + Sync;`, and another trait alias
290292/// `trait Bar = Read + Write`, then the bounds would expand to
291293/// `Read + Write + Sync + Send`.
294+ /// Expansion is done via a DFS (depth-first search), and the `visited` field
295+ /// is used to avoid cycles.
292296pub struct TraitAliasExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
293297 stack : Vec < TraitAliasExpansionInfo < ' tcx > > ,
294298 /// The set of predicates visited from the root directly to the current point in the
295- /// expansion tree.
299+ /// expansion tree (only containing trait aliases) .
296300 visited : PredicateSet < ' a , ' gcx , ' tcx > ,
297301}
298302
303+ /// Stores information about the expansion of a trait via a path of zero or more trait aliases.
299304#[ derive( Debug , Clone ) ]
300305pub struct TraitAliasExpansionInfo < ' tcx > {
301306 pub items : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
302307}
303308
304309impl < ' tcx > TraitAliasExpansionInfo < ' tcx > {
305- fn new ( trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> TraitAliasExpansionInfo < ' tcx > {
306- TraitAliasExpansionInfo {
310+ fn new ( trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
311+ Self {
307312 items : smallvec ! [ ( trait_ref, span) ]
308313 }
309314 }
310315
311- fn push ( & self , trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> TraitAliasExpansionInfo < ' tcx > {
316+ fn push ( & self , trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
312317 let mut items = self . items . clone ( ) ;
313318 items. push ( ( trait_ref, span) ) ;
314319
315- TraitAliasExpansionInfo {
320+ Self {
316321 items
317322 }
318323 }
@@ -330,6 +335,8 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
330335 }
331336}
332337
338+ /// Emits diagnostic information relating to the expansion of a trait via trait aliases
339+ /// (see [`TraitAliasExpansionInfo`]).
333340pub trait TraitAliasExpansionInfoDignosticBuilder {
334341 fn label_with_exp_info < ' tcx > ( & mut self ,
335342 info : & TraitAliasExpansionInfo < ' tcx > ,
@@ -365,24 +372,28 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>(
365372
366373impl < ' cx , ' gcx , ' tcx > TraitAliasExpander < ' cx , ' gcx , ' tcx > {
367374 /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
368- /// to the definition and pushes the resulting expansion onto `self.stack`, and returns `false`.
369- /// Otherwise, immediately returns `true` if `item` is a regular trait and `false` if it is a
375+ /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
376+ /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
370377 /// trait alias.
371- /// The return value indicates whether `item` should not be yielded to the user.
378+ /// The return value indicates whether `item` should be yielded to the user.
372379 fn push ( & mut self , item : & TraitAliasExpansionInfo < ' tcx > ) -> bool {
373380 let tcx = self . visited . tcx ;
374381 let trait_ref = item. trait_ref ( ) ;
375382 let pred = trait_ref. to_predicate ( ) ;
376383
377384 debug ! ( "expand_trait_aliases: trait_ref={:?}" , trait_ref) ;
378385
379- self . visited . remove ( & pred ) ;
380-
386+ // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of
387+ // already-visited predicates.
381388 let is_alias = tcx. is_trait_alias ( trait_ref. def_id ( ) ) ;
382389 if !is_alias || self . visited . contains ( & pred) {
383390 return !is_alias;
384391 }
385392
393+ // Remove the current predicate from the stack of already-visited ones, since we're doing
394+ // a DFS.
395+ self . visited . remove ( & pred) ;
396+
386397 // Get components of trait alias.
387398 let predicates = tcx. super_predicates_of ( trait_ref. def_id ( ) ) ;
388399
0 commit comments