From 81cc4822653b1f80729e8d50f9527c1fd0e5394f Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" <pnkfelix@pnkfx.org>
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<DefId>,
     ) -> 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" <pnkfelix@pnkfx.org>
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(xcrate_issue_61711_b::Struct)>(_: F) { }
+fn main() { }