@@ -51,13 +51,8 @@ struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
51
51
}
52
52
53
53
impl < ' a , ' gcx , ' tcx > PredicateSet < ' a , ' gcx , ' tcx > {
54
- fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> PredicateSet < ' a , ' gcx , ' tcx > {
55
- PredicateSet { tcx : tcx, set : Default :: default ( ) }
56
- }
57
-
58
- fn contains ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
59
- // See the `insert` method for why we use `anonymize_predicate` here.
60
- self . set . contains ( & anonymize_predicate ( self . tcx , pred) )
54
+ fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Self {
55
+ Self { tcx : tcx, set : Default :: default ( ) }
61
56
}
62
57
63
58
fn insert ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
@@ -73,11 +68,6 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
73
68
// regions before we throw things into the underlying set.
74
69
self . set . insert ( anonymize_predicate ( self . tcx , pred) )
75
70
}
76
-
77
- fn remove ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
78
- // See the `insert` method for why we use `anonymize_predicate` here.
79
- self . set . remove ( & anonymize_predicate ( self . tcx , pred) )
80
- }
81
71
}
82
72
83
73
impl < ' a , ' gcx , ' tcx , T : AsRef < ty:: Predicate < ' tcx > > > Extend < T > for PredicateSet < ' a , ' gcx , ' tcx > {
@@ -135,7 +125,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
135
125
FilterToTraits :: new ( self )
136
126
}
137
127
138
- fn push ( & mut self , predicate : & ty:: Predicate < ' tcx > ) {
128
+ fn elaborate ( & mut self , predicate : & ty:: Predicate < ' tcx > ) {
139
129
let tcx = self . visited . tcx ;
140
130
match * predicate {
141
131
ty:: Predicate :: Trait ( ref data) => {
@@ -153,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
153
143
// This is necessary to prevent infinite recursion in some
154
144
// cases. One common case is when people define
155
145
// `trait Sized: Sized { }` rather than `trait Sized { }`.
156
- predicates. retain ( |p | self . visited . insert ( p ) ) ;
146
+ predicates. retain ( |pred | self . visited . insert ( pred ) ) ;
157
147
158
148
self . stack . extend ( predicates) ;
159
149
}
@@ -251,15 +241,12 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
251
241
252
242
fn next ( & mut self ) -> Option < ty:: Predicate < ' tcx > > {
253
243
// Extract next item from top-most stack frame, if any.
254
- let next_predicate = match self . stack . pop ( ) {
255
- Some ( predicate) => predicate,
256
- None => {
257
- // No more stack frames. Done.
258
- return None ;
259
- }
260
- } ;
261
- self . push ( & next_predicate) ;
262
- return Some ( next_predicate) ;
244
+ if let Some ( pred) = self . stack . pop ( ) {
245
+ self . elaborate ( & pred) ;
246
+ Some ( pred)
247
+ } else {
248
+ None
249
+ }
263
250
}
264
251
}
265
252
@@ -294,31 +281,29 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
294
281
/// Expansion is done via a DFS (depth-first search), and the `visited` field
295
282
/// is used to avoid cycles.
296
283
pub struct TraitAliasExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
284
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
297
285
stack : Vec < TraitAliasExpansionInfo < ' tcx > > ,
298
- /// The set of predicates visited from the root directly to the current point in the
299
- /// expansion tree (only containing trait aliases).
300
- visited : PredicateSet < ' a , ' gcx , ' tcx > ,
301
286
}
302
287
303
288
/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
304
289
#[ derive( Debug , Clone ) ]
305
290
pub struct TraitAliasExpansionInfo < ' tcx > {
306
- pub items : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
291
+ pub path : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
307
292
}
308
293
309
294
impl < ' tcx > TraitAliasExpansionInfo < ' tcx > {
310
295
fn new ( trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
311
296
Self {
312
- items : smallvec ! [ ( trait_ref, span) ]
297
+ path : smallvec ! [ ( trait_ref, span) ]
313
298
}
314
299
}
315
300
316
- fn push ( & self , trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
317
- let mut items = self . items . clone ( ) ;
318
- items . push ( ( trait_ref, span) ) ;
301
+ fn clone_and_push ( & self , trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
302
+ let mut path = self . path . clone ( ) ;
303
+ path . push ( ( trait_ref, span) ) ;
319
304
320
305
Self {
321
- items
306
+ path
322
307
}
323
308
}
324
309
@@ -327,11 +312,11 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
327
312
}
328
313
329
314
pub fn top ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
330
- self . items . last ( ) . unwrap ( )
315
+ self . path . last ( ) . unwrap ( )
331
316
}
332
317
333
318
pub fn bottom ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
334
- self . items . first ( ) . unwrap ( )
319
+ self . path . first ( ) . unwrap ( )
335
320
}
336
321
}
337
322
@@ -340,21 +325,25 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
340
325
pub trait TraitAliasExpansionInfoDignosticBuilder {
341
326
fn label_with_exp_info < ' tcx > ( & mut self ,
342
327
info : & TraitAliasExpansionInfo < ' tcx > ,
343
- top_label : & str
328
+ top_label : & str ,
329
+ use_desc : & str
344
330
) -> & mut Self ;
345
331
}
346
332
347
333
impl < ' a > TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder < ' a > {
348
334
fn label_with_exp_info < ' tcx > ( & mut self ,
349
335
info : & TraitAliasExpansionInfo < ' tcx > ,
350
- top_label : & str
336
+ top_label : & str ,
337
+ use_desc : & str
351
338
) -> & mut Self {
352
339
self . span_label ( info. top ( ) . 1 , top_label) ;
353
- if info. items . len ( ) > 1 {
354
- for ( _, sp) in info. items [ 1 .. ( info. items . len ( ) - 1 ) ] . iter ( ) . rev ( ) {
355
- self . span_label ( * sp, "referenced here" ) ;
340
+ if info. path . len ( ) > 1 {
341
+ for ( _, sp) in info. path . iter ( ) . rev ( ) . skip ( 1 ) . take ( info. path . len ( ) - 2 ) {
342
+ self . span_label ( * sp, format ! ( "referenced here ({})" , use_desc ) ) ;
356
343
}
357
344
}
345
+ self . span_label ( info. bottom ( ) . 1 ,
346
+ format ! ( "trait alias used in trait object type ({})" , use_desc) ) ;
358
347
self
359
348
}
360
349
}
@@ -367,7 +356,7 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>(
367
356
. into_iter ( )
368
357
. map ( |( trait_ref, span) | TraitAliasExpansionInfo :: new ( trait_ref, span) )
369
358
. collect ( ) ;
370
- TraitAliasExpander { stack : items , visited : PredicateSet :: new ( tcx ) }
359
+ TraitAliasExpander { tcx , stack : items }
371
360
}
372
361
373
362
impl < ' cx , ' gcx , ' tcx > TraitAliasExpander < ' cx , ' gcx , ' tcx > {
@@ -376,23 +365,25 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
376
365
/// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
377
366
/// trait alias.
378
367
/// The return value indicates whether `item` should be yielded to the user.
379
- fn push ( & mut self , item : & TraitAliasExpansionInfo < ' tcx > ) -> bool {
380
- let tcx = self . visited . tcx ;
368
+ fn expand ( & mut self , item : & TraitAliasExpansionInfo < ' tcx > ) -> bool {
369
+ let tcx = self . tcx ;
381
370
let trait_ref = item. trait_ref ( ) ;
382
371
let pred = trait_ref. to_predicate ( ) ;
383
372
384
373
debug ! ( "expand_trait_aliases: trait_ref={:?}" , trait_ref) ;
385
374
386
- // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of
387
- // already-visited predicates.
375
+ // Don't recurse if this bound is not a trait alias.
388
376
let is_alias = tcx. is_trait_alias ( trait_ref. def_id ( ) ) ;
389
- if !is_alias || self . visited . contains ( & pred ) {
390
- return !is_alias ;
377
+ if !is_alias {
378
+ return true ;
391
379
}
392
380
393
- // Remove the current predicate from the stack of already-visited ones, since we're doing
394
- // a DFS.
395
- self . visited . remove ( & pred) ;
381
+ // Don't recurse if this trait alias is already on the stack for the DFS search.
382
+ let anon_pred = anonymize_predicate ( tcx, & pred) ;
383
+ if item. path . iter ( ) . rev ( ) . skip ( 1 )
384
+ . any ( |( tr, _) | anonymize_predicate ( tcx, & tr. to_predicate ( ) ) == anon_pred) {
385
+ return false ;
386
+ }
396
387
397
388
// Get components of trait alias.
398
389
let predicates = tcx. super_predicates_of ( trait_ref. def_id ( ) ) ;
@@ -403,16 +394,13 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
403
394
. filter_map ( |( pred, span) | {
404
395
pred. subst_supertrait ( tcx, & trait_ref)
405
396
. to_opt_poly_trait_ref ( )
406
- . map ( |trait_ref| item. push ( trait_ref, * span) )
397
+ . map ( |trait_ref| item. clone_and_push ( trait_ref, * span) )
407
398
} )
408
399
. collect ( ) ;
409
400
debug ! ( "expand_trait_aliases: items={:?}" , items) ;
410
401
411
402
self . stack . extend ( items) ;
412
403
413
- // Record predicate into set of already-visited.
414
- self . visited . insert ( & pred) ;
415
-
416
404
false
417
405
}
418
406
}
@@ -426,7 +414,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> {
426
414
427
415
fn next ( & mut self ) -> Option < TraitAliasExpansionInfo < ' tcx > > {
428
416
while let Some ( item) = self . stack . pop ( ) {
429
- if self . push ( & item) {
417
+ if self . expand ( & item) {
430
418
return Some ( item) ;
431
419
}
432
420
}
0 commit comments