1
+ use errors:: DiagnosticBuilder ;
2
+ use smallvec:: SmallVec ;
1
3
use syntax_pos:: Span ;
2
4
3
5
use crate :: hir;
@@ -43,7 +45,7 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
43
45
}
44
46
}
45
47
46
- struct PredicateSet < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
48
+ struct PredicateSet < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
47
49
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
48
50
set : FxHashSet < ty:: Predicate < ' tcx > > ,
49
51
}
@@ -53,6 +55,10 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
53
55
PredicateSet { tcx : tcx, set : Default :: default ( ) }
54
56
}
55
57
58
+ fn contains ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
59
+ self . set . contains ( & anonymize_predicate ( self . tcx , pred) )
60
+ }
61
+
56
62
fn insert ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
57
63
// We have to be careful here because we want
58
64
//
@@ -66,6 +72,18 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
66
72
// regions before we throw things into the underlying set.
67
73
self . set . insert ( anonymize_predicate ( self . tcx , pred) )
68
74
}
75
+
76
+ fn remove ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
77
+ self . set . remove ( & anonymize_predicate ( self . tcx , pred) )
78
+ }
79
+ }
80
+
81
+ impl < ' a , ' gcx , ' tcx , T : AsRef < ty:: Predicate < ' tcx > > > Extend < T > for PredicateSet < ' a , ' gcx , ' tcx > {
82
+ fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
83
+ for pred in iter. into_iter ( ) {
84
+ self . insert ( pred. as_ref ( ) ) ;
85
+ }
86
+ }
69
87
}
70
88
71
89
///////////////////////////////////////////////////////////////////////////
@@ -230,10 +248,16 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
230
248
}
231
249
232
250
fn next ( & mut self ) -> Option < ty:: Predicate < ' tcx > > {
233
- self . stack . pop ( ) . map ( |item| {
234
- self . push ( & item) ;
235
- item
236
- } )
251
+ // Extract next item from top-most stack frame, if any.
252
+ let next_predicate = match self . stack . pop ( ) {
253
+ Some ( predicate) => predicate,
254
+ None => {
255
+ // No more stack frames. Done.
256
+ return None ;
257
+ }
258
+ } ;
259
+ self . push ( & next_predicate) ;
260
+ return Some ( next_predicate) ;
237
261
}
238
262
}
239
263
@@ -256,96 +280,140 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
256
280
}
257
281
258
282
///////////////////////////////////////////////////////////////////////////
259
- // `TraitRefExpander ` iterator
283
+ // `TraitAliasExpander ` iterator
260
284
///////////////////////////////////////////////////////////////////////////
261
285
262
- /// "Trait reference expansion" is the process of expanding a sequence of trait
286
+ /// "Trait alias expansion" is the process of expanding a sequence of trait
263
287
/// references into another sequence by transitively following all trait
264
288
/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
265
289
/// `trait Foo = Bar + Sync;`, and another trait alias
266
290
/// `trait Bar = Read + Write`, then the bounds would expand to
267
291
/// `Read + Write + Sync + Send`.
268
- pub struct TraitRefExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
269
- stack : Vec < TraitRefExpansionInfo < ' tcx > > ,
292
+ pub struct TraitAliasExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
293
+ stack : Vec < TraitAliasExpansionInfo < ' tcx > > ,
294
+ /// The set of predicates visited from the root directly to the current point in the
295
+ /// expansion tree.
270
296
visited : PredicateSet < ' a , ' gcx , ' tcx > ,
271
297
}
272
298
273
299
#[ derive( Debug , Clone ) ]
274
- pub struct TraitRefExpansionInfo < ' tcx > {
275
- pub top_level_trait_ref : ty:: PolyTraitRef < ' tcx > ,
276
- pub top_level_span : Span ,
277
- pub trait_ref : ty:: PolyTraitRef < ' tcx > ,
278
- pub span : Span ,
300
+ pub struct TraitAliasExpansionInfo < ' tcx > {
301
+ pub items : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
279
302
}
280
303
281
- pub fn expand_trait_refs < ' cx , ' gcx , ' tcx > (
304
+ impl < ' tcx > TraitAliasExpansionInfo < ' tcx > {
305
+ fn new ( trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> TraitAliasExpansionInfo < ' tcx > {
306
+ TraitAliasExpansionInfo {
307
+ items : smallvec ! [ ( trait_ref, span) ]
308
+ }
309
+ }
310
+
311
+ fn push ( & self , trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> TraitAliasExpansionInfo < ' tcx > {
312
+ let mut items = self . items . clone ( ) ;
313
+ items. push ( ( trait_ref, span) ) ;
314
+
315
+ TraitAliasExpansionInfo {
316
+ items
317
+ }
318
+ }
319
+
320
+ pub fn trait_ref ( & self ) -> & ty:: PolyTraitRef < ' tcx > {
321
+ & self . top ( ) . 0
322
+ }
323
+
324
+ pub fn top ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
325
+ self . items . last ( ) . unwrap ( )
326
+ }
327
+
328
+ pub fn bottom ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
329
+ self . items . first ( ) . unwrap ( )
330
+ }
331
+ }
332
+
333
+ pub trait TraitAliasExpansionInfoDignosticBuilder {
334
+ fn label_with_exp_info < ' tcx > ( & mut self ,
335
+ info : & TraitAliasExpansionInfo < ' tcx > ,
336
+ top_label : & str
337
+ ) -> & mut Self ;
338
+ }
339
+
340
+ impl < ' a > TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder < ' a > {
341
+ fn label_with_exp_info < ' tcx > ( & mut self ,
342
+ info : & TraitAliasExpansionInfo < ' tcx > ,
343
+ top_label : & str
344
+ ) -> & mut Self {
345
+ self . span_label ( info. top ( ) . 1 , top_label) ;
346
+ if info. items . len ( ) > 1 {
347
+ for ( _, sp) in info. items [ 1 ..( info. items . len ( ) - 1 ) ] . iter ( ) . rev ( ) {
348
+ self . span_label ( * sp, "referenced here" ) ;
349
+ }
350
+ }
351
+ self
352
+ }
353
+ }
354
+
355
+ pub fn expand_trait_aliases < ' cx , ' gcx , ' tcx > (
282
356
tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
283
357
trait_refs : impl IntoIterator < Item = ( ty:: PolyTraitRef < ' tcx > , Span ) >
284
- ) -> TraitRefExpander < ' cx , ' gcx , ' tcx > {
285
- let mut visited = PredicateSet :: new ( tcx) ;
286
- let mut items: Vec < _ > =
287
- trait_refs
288
- . into_iter ( )
289
- . map ( |( trait_ref, span) | TraitRefExpansionInfo {
290
- top_level_trait_ref : trait_ref. clone ( ) ,
291
- top_level_span : span,
292
- trait_ref,
293
- span,
294
- } )
295
- . collect ( ) ;
296
- items. retain ( |item| visited. insert ( & item. trait_ref . to_predicate ( ) ) ) ;
297
- TraitRefExpander { stack : items, visited }
358
+ ) -> TraitAliasExpander < ' cx , ' gcx , ' tcx > {
359
+ let items: Vec < _ > = trait_refs
360
+ . into_iter ( )
361
+ . map ( |( trait_ref, span) | TraitAliasExpansionInfo :: new ( trait_ref, span) )
362
+ . collect ( ) ;
363
+ TraitAliasExpander { stack : items, visited : PredicateSet :: new ( tcx) }
298
364
}
299
365
300
- impl < ' cx , ' gcx , ' tcx > TraitRefExpander < ' cx , ' gcx , ' tcx > {
301
- /// If `item` refers to a trait alias, adds the components of the trait alias to the stack,
302
- /// and returns `false`.
303
- /// If `item` refers to an ordinary trait, simply returns `true`.
304
- fn push ( & mut self , item : & TraitRefExpansionInfo < ' tcx > ) -> bool {
366
+ impl < ' cx , ' gcx , ' tcx > TraitAliasExpander < ' cx , ' gcx , ' tcx > {
367
+ /// 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
370
+ /// trait alias.
371
+ /// The return value indicates whether `item` should not be yielded to the user.
372
+ fn push ( & mut self , item : & TraitAliasExpansionInfo < ' tcx > ) -> bool {
305
373
let tcx = self . visited . tcx ;
374
+ let trait_ref = item. trait_ref ( ) ;
375
+ let pred = trait_ref. to_predicate ( ) ;
376
+
377
+ debug ! ( "expand_trait_aliases: trait_ref={:?}" , trait_ref) ;
378
+
379
+ self . visited . remove ( & pred) ;
306
380
307
- if !tcx. is_trait_alias ( item. trait_ref . def_id ( ) ) {
308
- return true ;
381
+ let is_alias = tcx. is_trait_alias ( trait_ref. def_id ( ) ) ;
382
+ if !is_alias || self . visited . contains ( & pred) {
383
+ return !is_alias;
309
384
}
310
385
311
- // Get components of the trait alias.
312
- let predicates = tcx. super_predicates_of ( item . trait_ref . def_id ( ) ) ;
386
+ // Get components of trait alias.
387
+ let predicates = tcx. super_predicates_of ( trait_ref. def_id ( ) ) ;
313
388
314
- let mut items: Vec < _ > = predicates. predicates
389
+ let items: Vec < _ > = predicates. predicates
315
390
. iter ( )
316
391
. rev ( )
317
392
. filter_map ( |( pred, span) | {
318
- pred. subst_supertrait ( tcx, & item . trait_ref )
393
+ pred. subst_supertrait ( tcx, & trait_ref)
319
394
. to_opt_poly_trait_ref ( )
320
- . map ( |trait_ref|
321
- TraitRefExpansionInfo {
322
- trait_ref,
323
- span : * span,
324
- ..* item
325
- }
326
- )
395
+ . map ( |trait_ref| item. push ( trait_ref, * span) )
327
396
} )
328
397
. collect ( ) ;
398
+ debug ! ( "expand_trait_aliases: items={:?}" , items) ;
329
399
330
- debug ! ( "trait_ref_expander: trait_ref={:?} items={:?}" ,
331
- item. trait_ref, items) ;
400
+ self . stack . extend ( items) ;
332
401
333
- // Only keep those items that we haven't already seen .
334
- items . retain ( |i| self . visited . insert ( & i . trait_ref . to_predicate ( ) ) ) ;
402
+ // Record predicate into set of already-visited .
403
+ self . visited . insert ( & pred ) ;
335
404
336
- self . stack . extend ( items) ;
337
405
false
338
406
}
339
407
}
340
408
341
- impl < ' cx , ' gcx , ' tcx > Iterator for TraitRefExpander < ' cx , ' gcx , ' tcx > {
342
- type Item = TraitRefExpansionInfo < ' tcx > ;
409
+ impl < ' cx , ' gcx , ' tcx > Iterator for TraitAliasExpander < ' cx , ' gcx , ' tcx > {
410
+ type Item = TraitAliasExpansionInfo < ' tcx > ;
343
411
344
412
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
345
413
( self . stack . len ( ) , None )
346
414
}
347
415
348
- fn next ( & mut self ) -> Option < TraitRefExpansionInfo < ' tcx > > {
416
+ fn next ( & mut self ) -> Option < TraitAliasExpansionInfo < ' tcx > > {
349
417
while let Some ( item) = self . stack . pop ( ) {
350
418
if self . push ( & item) {
351
419
return Some ( item) ;
@@ -386,8 +454,8 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> {
386
454
self . stack . extend (
387
455
predicates. predicates
388
456
. iter ( )
389
- . filter_map ( |( p , _) | p . to_opt_poly_trait_ref ( ) )
390
- . map ( |t| t . def_id ( ) )
457
+ . filter_map ( |( pred , _) | pred . to_opt_poly_trait_ref ( ) )
458
+ . map ( |trait_ref| trait_ref . def_id ( ) )
391
459
. filter ( |& super_def_id| visited. insert ( super_def_id) ) ) ;
392
460
Some ( def_id)
393
461
}
@@ -413,17 +481,12 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<
413
481
type Item = ty:: PolyTraitRef < ' tcx > ;
414
482
415
483
fn next ( & mut self ) -> Option < ty:: PolyTraitRef < ' tcx > > {
416
- loop {
417
- match self . base_iterator . next ( ) {
418
- None => {
419
- return None ;
420
- }
421
- Some ( ty:: Predicate :: Trait ( data) ) => {
422
- return Some ( data. to_poly_trait_ref ( ) ) ;
423
- }
424
- Some ( _) => { }
484
+ while let Some ( pred) = self . base_iterator . next ( ) {
485
+ if let ty:: Predicate :: Trait ( data) = pred {
486
+ return Some ( data. to_poly_trait_ref ( ) ) ;
425
487
}
426
488
}
489
+ None
427
490
}
428
491
429
492
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
0 commit comments