@@ -51,13 +51,8 @@ struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
5151}
5252
5353impl < ' 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 ( ) }
6156 }
6257
6358 fn insert ( & mut self , pred : & ty:: Predicate < ' tcx > ) -> bool {
@@ -73,11 +68,6 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
7368 // regions before we throw things into the underlying set.
7469 self . set . insert ( anonymize_predicate ( self . tcx , pred) )
7570 }
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- }
8171}
8272
8373impl < ' 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> {
135125 FilterToTraits :: new ( self )
136126 }
137127
138- fn push ( & mut self , predicate : & ty:: Predicate < ' tcx > ) {
128+ fn elaborate ( & mut self , predicate : & ty:: Predicate < ' tcx > ) {
139129 let tcx = self . visited . tcx ;
140130 match * predicate {
141131 ty:: Predicate :: Trait ( ref data) => {
@@ -153,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
153143 // This is necessary to prevent infinite recursion in some
154144 // cases. One common case is when people define
155145 // `trait Sized: Sized { }` rather than `trait Sized { }`.
156- predicates. retain ( |p | self . visited . insert ( p ) ) ;
146+ predicates. retain ( |pred | self . visited . insert ( pred ) ) ;
157147
158148 self . stack . extend ( predicates) ;
159149 }
@@ -251,15 +241,12 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
251241
252242 fn next ( & mut self ) -> Option < ty:: Predicate < ' tcx > > {
253243 // 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+ }
263250 }
264251}
265252
@@ -294,31 +281,29 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
294281/// Expansion is done via a DFS (depth-first search), and the `visited` field
295282/// is used to avoid cycles.
296283pub struct TraitAliasExpander < ' a , ' gcx : ' a + ' tcx , ' tcx : ' a > {
284+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
297285 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 > ,
301286}
302287
303288/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
304289#[ derive( Debug , Clone ) ]
305290pub struct TraitAliasExpansionInfo < ' tcx > {
306- pub items : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
291+ pub path : SmallVec < [ ( ty:: PolyTraitRef < ' tcx > , Span ) ; 4 ] > ,
307292}
308293
309294impl < ' tcx > TraitAliasExpansionInfo < ' tcx > {
310295 fn new ( trait_ref : ty:: PolyTraitRef < ' tcx > , span : Span ) -> Self {
311296 Self {
312- items : smallvec ! [ ( trait_ref, span) ]
297+ path : smallvec ! [ ( trait_ref, span) ]
313298 }
314299 }
315300
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) ) ;
319304
320305 Self {
321- items
306+ path
322307 }
323308 }
324309
@@ -327,11 +312,11 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
327312 }
328313
329314 pub fn top ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
330- self . items . last ( ) . unwrap ( )
315+ self . path . last ( ) . unwrap ( )
331316 }
332317
333318 pub fn bottom ( & self ) -> & ( ty:: PolyTraitRef < ' tcx > , Span ) {
334- self . items . first ( ) . unwrap ( )
319+ self . path . first ( ) . unwrap ( )
335320 }
336321}
337322
@@ -340,21 +325,25 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
340325pub trait TraitAliasExpansionInfoDignosticBuilder {
341326 fn label_with_exp_info < ' tcx > ( & mut self ,
342327 info : & TraitAliasExpansionInfo < ' tcx > ,
343- top_label : & str
328+ top_label : & str ,
329+ use_desc : & str
344330 ) -> & mut Self ;
345331}
346332
347333impl < ' a > TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder < ' a > {
348334 fn label_with_exp_info < ' tcx > ( & mut self ,
349335 info : & TraitAliasExpansionInfo < ' tcx > ,
350- top_label : & str
336+ top_label : & str ,
337+ use_desc : & str
351338 ) -> & mut Self {
352339 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 ) ) ;
356343 }
357344 }
345+ self . span_label ( info. bottom ( ) . 1 ,
346+ format ! ( "trait alias used in trait object type ({})" , use_desc) ) ;
358347 self
359348 }
360349}
@@ -367,7 +356,7 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>(
367356 . into_iter ( )
368357 . map ( |( trait_ref, span) | TraitAliasExpansionInfo :: new ( trait_ref, span) )
369358 . collect ( ) ;
370- TraitAliasExpander { stack : items , visited : PredicateSet :: new ( tcx ) }
359+ TraitAliasExpander { tcx , stack : items }
371360}
372361
373362impl < ' cx , ' gcx , ' tcx > TraitAliasExpander < ' cx , ' gcx , ' tcx > {
@@ -376,23 +365,25 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
376365 /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
377366 /// trait alias.
378367 /// 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 ;
381370 let trait_ref = item. trait_ref ( ) ;
382371 let pred = trait_ref. to_predicate ( ) ;
383372
384373 debug ! ( "expand_trait_aliases: trait_ref={:?}" , trait_ref) ;
385374
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.
388376 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 ;
391379 }
392380
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+ }
396387
397388 // Get components of trait alias.
398389 let predicates = tcx. super_predicates_of ( trait_ref. def_id ( ) ) ;
@@ -403,16 +394,13 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
403394 . filter_map ( |( pred, span) | {
404395 pred. subst_supertrait ( tcx, & trait_ref)
405396 . 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) )
407398 } )
408399 . collect ( ) ;
409400 debug ! ( "expand_trait_aliases: items={:?}" , items) ;
410401
411402 self . stack . extend ( items) ;
412403
413- // Record predicate into set of already-visited.
414- self . visited . insert ( & pred) ;
415-
416404 false
417405 }
418406}
@@ -426,7 +414,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> {
426414
427415 fn next ( & mut self ) -> Option < TraitAliasExpansionInfo < ' tcx > > {
428416 while let Some ( item) = self . stack . pop ( ) {
429- if self . push ( & item) {
417+ if self . expand ( & item) {
430418 return Some ( item) ;
431419 }
432420 }
0 commit comments