about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-10-17 18:18:55 +0200
committerGitHub <noreply@github.com>2021-10-17 18:18:55 +0200
commit59dc2187adebcbe6fca9073b5410c51c64915f95 (patch)
treedaffe2d01cd3dee5df22ffa1330f94bb7ff8ec25 /compiler
parent6f53ddfa74ac3c10ceb63ad4a7a9c95e55853c87 (diff)
parentf14e8dd4e719bd29c6f559ffffa9a17317f4af1e (diff)
downloadrust-59dc2187adebcbe6fca9073b5410c51c64915f95.tar.gz
rust-59dc2187adebcbe6fca9073b5410c51c64915f95.zip
Rollup merge of #89738 - eddyb:extern-crate-recursion, r=nagisa
ty::pretty: prevent infinite recursion for `extern crate` paths.

Fixes #55779, fixes #87932.

This fix is based on `@estebank's` idea in https://github.com/rust-lang/rust/issues/55779#issuecomment-614758510 - but instead of trying to get `try_print_visible_def_path_recur`'s cycle detection to work in this case, this PR "just" disables the "visible path" feature when printing the path to an `extern crate`, so that the old recursion chain of `try_print_visible_def_path -> print_def_path -> try_print_visible_def_path`, is now impossible.

Both tests have been confirmed to crash `rustc` because of a stack overflow, without the fix.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs28
1 files changed, 18 insertions, 10 deletions
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2610a76b281..b11a54d5dcb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -350,18 +350,26 @@ pub trait PrettyPrinter<'tcx>:
             match self.tcx().extern_crate(def_id) {
                 Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
                     (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
-                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
-                        return Ok((
-                            if !span.is_dummy() {
-                                self.print_def_path(def_id, &[])?
-                            } else {
-                                self.path_crate(cnum)?
-                            },
-                            true,
-                        ));
+                        // NOTE(eddyb) the only reason `span` might be dummy,
+                        // that we're aware of, is that it's the `std`/`core`
+                        // `extern crate` injected by default.
+                        // FIXME(eddyb) find something better to key this on,
+                        // or avoid ending up with `ExternCrateSource::Extern`,
+                        // for the injected `std`/`core`.
+                        if span.is_dummy() {
+                            return Ok((self.path_crate(cnum)?, true));
+                        }
+
+                        // Disable `try_print_trimmed_def_path` behavior within
+                        // the `print_def_path` call, to avoid infinite recursion
+                        // in cases where the `extern crate foo` has non-trivial
+                        // parents, e.g. it's nested in `impl foo::Trait for Bar`
+                        // (see also issues #55779 and #87932).
+                        self = with_no_visible_paths(|| self.print_def_path(def_id, &[]))?;
+
+                        return Ok((self, true));
                     }
                     (ExternCrateSource::Path, LOCAL_CRATE) => {
-                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
                         return Ok((self.path_crate(cnum)?, true));
                     }
                     _ => {}