From 81cc4822653b1f80729e8d50f9527c1fd0e5394f Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 8 Jul 2019 22:26:15 +0200 Subject: [PATCH 1/2] Avoid infinite looping in `print_def_path`. --- src/librustc/ty/print/pretty.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index cb0ac0f07f287..e889f2edef2bb 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -228,8 +228,27 @@ pub trait PrettyPrinter<'tcx>: /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path( + self, + def_id: DefId, + ) -> Result<(Self, bool), Self::Error> { + let mut callers = Vec::new(); + self.try_print_visible_def_path_recur(def_id, &mut callers) + } + + /// Does the work of `try_print_visible_def_path`, building the + /// full definition path recursively before attempting to + /// post-process it into the valid and visible version that + /// accounts for re-exports. + /// + /// This method should only be callled by itself or + /// `try_print_visible_def_path`. + /// + /// `callers` is a chain of visible_parent's leading to `def_id`, + /// to support cycle detection during recursion. + fn try_print_visible_def_path_recur( mut self, def_id: DefId, + callers: &mut Vec, ) -> Result<(Self, bool), Self::Error> { define_scoped_cx!(self); @@ -302,14 +321,19 @@ pub trait PrettyPrinter<'tcx>: Some(parent) => parent, None => return Ok((self, false)), }; + if callers.contains(&visible_parent) { + return Ok((self, false)); + } + callers.push(visible_parent); // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid // knowing ahead of time whether the entire path will succeed or not. // To support printers that do not implement `PrettyPrinter`, a `Vec` or // linked list on the stack would need to be built, before any printing. - match self.try_print_visible_def_path(visible_parent)? { + match self.try_print_visible_def_path_recur(visible_parent, callers)? { (cx, false) => return Ok((cx, false)), (cx, true) => self = cx, } + callers.pop(); let actual_parent = self.tcx().parent(def_id); debug!( "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", From 4c58b29285015f6d7739e342e09bf3be7eea3b12 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 8 Jul 2019 17:04:02 +0200 Subject: [PATCH 2/2] regression test. --- src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs | 5 +++++ .../issues/issue-61711-once-caused-rustc-inf-loop.rs | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs create mode 100644 src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs diff --git a/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs b/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs new file mode 100644 index 0000000000000..88a040529e709 --- /dev/null +++ b/src/test/ui/issues/auxiliary/xcrate-issue-61711-b.rs @@ -0,0 +1,5 @@ +// edition:2018 +#![crate_type="lib"] +#![crate_name="xcrate_issue_61711_b"] +pub struct Struct; +pub use crate as alias; diff --git a/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs new file mode 100644 index 0000000000000..8fc09c89f786b --- /dev/null +++ b/src/test/ui/issues/issue-61711-once-caused-rustc-inf-loop.rs @@ -0,0 +1,11 @@ +// Issue 61711: A crate pub re-exporting `crate` was causing an +// infinite loop. + +// edition:2018 +// aux-build:xcrate-issue-61711-b.rs +// compile-flags:--extern xcrate_issue_61711_b + +// run-pass + +fn f(_: F) { } +fn main() { }