1+ use errors:: DiagnosticBuilder ;
2+ use smallvec:: SmallVec ;
13use syntax_pos:: Span ;
24
35use crate :: hir;
@@ -43,7 +45,7 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
4345 }
4446}
4547
46- struct PredicateSet < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
48+ struct PredicateSet < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
4749 tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
4850 set : FxHashSet < ty:: Predicate < ' tcx > > ,
4951}
@@ -53,6 +55,10 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
5355 PredicateSet { tcx : tcx, set : Default :: default ( ) }
5456 }
5557
58+ fn contains ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
59+ self . set . contains ( & anonymize_predicate ( self . tcx , pred) )
60+ }
61+
5662 fn insert ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
5763 // We have to be careful here because we want
5864 //
@@ -66,6 +72,18 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
6672 // regions before we throw things into the underlying set.
6773 self . set . insert ( anonymize_predicate ( self . tcx , pred) )
6874 }
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+ }
6987}
7088
7189///////////////////////////////////////////////////////////////////////////
@@ -230,10 +248,16 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
230248 }
231249
232250 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) ;
237261 }
238262}
239263
@@ -256,96 +280,140 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
256280}
257281
258282///////////////////////////////////////////////////////////////////////////
259- // `TraitRefExpander ` iterator
283+ // `TraitAliasExpander ` iterator
260284///////////////////////////////////////////////////////////////////////////
261285
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
263287/// references into another sequence by transitively following all trait
264288/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
265289/// `trait Foo = Bar + Sync;`, and another trait alias
266290/// `trait Bar = Read + Write`, then the bounds would expand to
267291/// `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.
270296 visited : PredicateSet < ' a , ' gcx , ' tcx > ,
271297}
272298
273299#[ 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 ] > ,
279302}
280303
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 > (
282356 tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
283357 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) }
298364}
299365
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 {
305373 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) ;
306380
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;
309384 }
310385
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 ( ) ) ;
313388
314- let mut items: Vec < _ > = predicates. predicates
389+ let items: Vec < _ > = predicates. predicates
315390 . iter ( )
316391 . rev ( )
317392 . filter_map ( |( pred, span) | {
318- pred. subst_supertrait ( tcx, & item . trait_ref )
393+ pred. subst_supertrait ( tcx, & trait_ref)
319394 . 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) )
327396 } )
328397 . collect ( ) ;
398+ debug ! ( "expand_trait_aliases: items={:?}" , items) ;
329399
330- debug ! ( "trait_ref_expander: trait_ref={:?} items={:?}" ,
331- item. trait_ref, items) ;
400+ self . stack . extend ( items) ;
332401
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 ) ;
335404
336- self . stack . extend ( items) ;
337405 false
338406 }
339407}
340408
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 > ;
343411
344412 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
345413 ( self . stack . len ( ) , None )
346414 }
347415
348- fn next ( & mut self ) -> Option < TraitRefExpansionInfo < ' tcx > > {
416+ fn next ( & mut self ) -> Option < TraitAliasExpansionInfo < ' tcx > > {
349417 while let Some ( item) = self . stack . pop ( ) {
350418 if self . push ( & item) {
351419 return Some ( item) ;
@@ -386,8 +454,8 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> {
386454 self . stack . extend (
387455 predicates. predicates
388456 . 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 ( ) )
391459 . filter ( |& super_def_id| visited. insert ( super_def_id) ) ) ;
392460 Some ( def_id)
393461 }
@@ -413,17 +481,12 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<
413481 type Item = ty:: PolyTraitRef < ' tcx > ;
414482
415483 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 ( ) ) ;
425487 }
426488 }
489+ None
427490 }
428491
429492 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
0 commit comments