@@ -56,6 +56,7 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
56
56
}
57
57
58
58
fn contains ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
59
+ // See the `insert` method for why we use `anonymize_predicate` here.
59
60
self . set . contains ( & anonymize_predicate ( self . tcx , pred) )
60
61
}
61
62
@@ -74,13 +75,14 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
74
75
}
75
76
76
77
fn remove ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
78
+ // See the `insert` method for why we use `anonymize_predicate` here.
77
79
self . set . remove ( & anonymize_predicate ( self . tcx , pred) )
78
80
}
79
81
}
80
82
81
83
impl < ' a , ' gcx , ' tcx , T : AsRef < ty:: Predicate < ' tcx > > > Extend < T > for PredicateSet < ' a , ' gcx , ' tcx > {
82
84
fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
83
- for pred in iter. into_iter ( ) {
85
+ for pred in iter {
84
86
self . insert ( pred. as_ref ( ) ) ;
85
87
}
86
88
}
@@ -289,30 +291,33 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
289
291
/// `trait Foo = Bar + Sync;`, and another trait alias
290
292
/// `trait Bar = Read + Write`, then the bounds would expand to
291
293
/// `Read + Write + Sync + Send`.
294
+ /// Expansion is done via a DFS (depth-first search), and the `visited` field
295
+ /// is used to avoid cycles.
292
296
pub struct TraitAliasExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
293
297
stack : Vec < TraitAliasExpansionInfo < ' tcx > > ,
294
298
/// 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) .
296
300
visited : PredicateSet < ' a , ' gcx , ' tcx > ,
297
301
}
298
302
303
+ /// Stores information about the expansion of a trait via a path of zero or more trait aliases.
299
304
#[ derive( Debug , Clone ) ]
300
305
pub struct TraitAliasExpansionInfo < ' tcx > {
301
306
pub items : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
302
307
}
303
308
304
309
impl < ' 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 {
307
312
items : smallvec ! [ ( trait_ref, span) ]
308
313
}
309
314
}
310
315
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 {
312
317
let mut items = self . items . clone ( ) ;
313
318
items. push ( ( trait_ref, span) ) ;
314
319
315
- TraitAliasExpansionInfo {
320
+ Self {
316
321
items
317
322
}
318
323
}
@@ -330,6 +335,8 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
330
335
}
331
336
}
332
337
338
+ /// Emits diagnostic information relating to the expansion of a trait via trait aliases
339
+ /// (see [`TraitAliasExpansionInfo`]).
333
340
pub trait TraitAliasExpansionInfoDignosticBuilder {
334
341
fn label_with_exp_info < ' tcx > ( & mut self ,
335
342
info : & TraitAliasExpansionInfo < ' tcx > ,
@@ -365,24 +372,28 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>(
365
372
366
373
impl < ' cx , ' gcx , ' tcx > TraitAliasExpander < ' cx , ' gcx , ' tcx > {
367
374
/// 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
370
377
/// 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.
372
379
fn push ( & mut self , item : & TraitAliasExpansionInfo < ' tcx > ) -> bool {
373
380
let tcx = self . visited . tcx ;
374
381
let trait_ref = item. trait_ref ( ) ;
375
382
let pred = trait_ref. to_predicate ( ) ;
376
383
377
384
debug ! ( "expand_trait_aliases: trait_ref={:?}" , trait_ref) ;
378
385
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.
381
388
let is_alias = tcx. is_trait_alias ( trait_ref. def_id ( ) ) ;
382
389
if !is_alias || self . visited . contains ( & pred) {
383
390
return !is_alias;
384
391
}
385
392
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
+
386
397
// Get components of trait alias.
387
398
let predicates = tcx. super_predicates_of ( trait_ref. def_id ( ) ) ;
388
399
0 commit comments