@@ -228,8 +228,27 @@ pub trait PrettyPrinter<'tcx>:
228228 /// from at least one local module and returns true. If the crate defining `def_id` is
229229 /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
230230 fn try_print_visible_def_path (
231+ self ,
232+ def_id : DefId ,
233+ ) -> Result < ( Self , bool ) , Self :: Error > {
234+ let mut callers = Vec :: new ( ) ;
235+ self . try_print_visible_def_path_recur ( def_id, & mut callers)
236+ }
237+
238+ /// Does the work of `try_print_visible_def_path`, building the
239+ /// full definition path recursively before attempting to
240+ /// post-process it into the valid and visible version that
241+ /// accounts for re-exports.
242+ ///
243+ /// This method should only be callled by itself or
244+ /// `try_print_visible_def_path`.
245+ ///
246+ /// `callers` is a chain of visible_parent's leading to `def_id`,
247+ /// to support cycle detection during recursion.
248+ fn try_print_visible_def_path_recur (
231249 mut self ,
232250 def_id : DefId ,
251+ callers : & mut Vec < DefId > ,
233252 ) -> Result < ( Self , bool ) , Self :: Error > {
234253 define_scoped_cx ! ( self ) ;
235254
@@ -302,14 +321,19 @@ pub trait PrettyPrinter<'tcx>:
302321 Some ( parent) => parent,
303322 None => return Ok ( ( self , false ) ) ,
304323 } ;
324+ if callers. contains ( & visible_parent) {
325+ return Ok ( ( self , false ) ) ;
326+ }
327+ callers. push ( visible_parent) ;
305328 // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
306329 // knowing ahead of time whether the entire path will succeed or not.
307330 // To support printers that do not implement `PrettyPrinter`, a `Vec` or
308331 // linked list on the stack would need to be built, before any printing.
309- match self . try_print_visible_def_path ( visible_parent) ? {
332+ match self . try_print_visible_def_path_recur ( visible_parent, callers ) ? {
310333 ( cx, false ) => return Ok ( ( cx, false ) ) ,
311334 ( cx, true ) => self = cx,
312335 }
336+ callers. pop ( ) ;
313337 let actual_parent = self . tcx ( ) . parent ( def_id) ;
314338 debug ! (
315339 "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}" ,
0 commit comments