From 152e40377aefe966486515c392d741f851510a8a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 10 Oct 2021 18:18:30 +0300 Subject: [PATCH 1/2] ty::pretty: document "dummy Span extern crate" special-case in `try_print_visible_def_path_recur`. --- compiler/rustc_middle/src/ty/print/pretty.rs | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2610a76b2810b..ae0cc97c7044e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -350,18 +350,19 @@ 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)); + } + + return Ok((self.print_def_path(def_id, &[])?, true)); } (ExternCrateSource::Path, LOCAL_CRATE) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((self.path_crate(cnum)?, true)); } _ => {} From f14e8dd4e719bd29c6f559ffffa9a17317f4af1e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 10 Oct 2021 18:50:44 +0300 Subject: [PATCH 2/2] ty::pretty: prevent infinite recursion for `extern crate` paths. --- compiler/rustc_middle/src/ty/print/pretty.rs | 9 +++++- .../auxiliary/issue-55779-extern-trait.rs | 1 + .../uniform-paths/auxiliary/issue-87932-a.rs | 3 ++ .../ui/rust-2018/uniform-paths/issue-55779.rs | 29 +++++++++++++++++++ .../ui/rust-2018/uniform-paths/issue-87932.rs | 15 ++++++++++ .../uniform-paths/issue-87932.stderr | 18 ++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-55779.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-87932.rs create mode 100644 src/test/ui/rust-2018/uniform-paths/issue-87932.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ae0cc97c7044e..b11a54d5dcb11 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -360,7 +360,14 @@ pub trait PrettyPrinter<'tcx>: return Ok((self.path_crate(cnum)?, true)); } - return Ok((self.print_def_path(def_id, &[])?, 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) => { return Ok((self.path_crate(cnum)?, true)); diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs new file mode 100644 index 0000000000000..1ce9841c1a8c5 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs @@ -0,0 +1 @@ +pub trait Trait { fn no_op(&self); } diff --git a/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs new file mode 100644 index 0000000000000..8fd2d77be3910 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs @@ -0,0 +1,3 @@ +pub trait Deserialize { + fn deserialize(); +} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-55779.rs b/src/test/ui/rust-2018/uniform-paths/issue-55779.rs new file mode 100644 index 0000000000000..0af17a89b17bf --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-55779.rs @@ -0,0 +1,29 @@ +// run-pass +// edition:2018 +// aux-crate:issue_55779_extern_trait=issue-55779-extern-trait.rs + +use issue_55779_extern_trait::Trait; + +struct Local; +struct Helper; + +impl Trait for Local { + fn no_op(&self) + { + // (Unused) extern crate declaration necessary to reproduce bug + extern crate issue_55779_extern_trait; + + // This one works + // impl Trait for Helper { fn no_op(&self) { } } + + // This one infinite-loops + const _IMPL_SERIALIZE_FOR_HELPER: () = { + // (extern crate can also appear here to reproduce bug, + // as in originating example from serde) + impl Trait for Helper { fn no_op(&self) { } } + }; + + } +} + +fn main() { } diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.rs b/src/test/ui/rust-2018/uniform-paths/issue-87932.rs new file mode 100644 index 0000000000000..70a641d8a47ad --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.rs @@ -0,0 +1,15 @@ +// edition:2018 +// aux-crate:issue_87932_a=issue-87932-a.rs + +pub struct A {} + +impl issue_87932_a::Deserialize for A { + fn deserialize() { + extern crate issue_87932_a as _a; + } +} + +fn main() { + A::deserialize(); + //~^ ERROR no function or associated item named `deserialize` found for struct `A` +} diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr new file mode 100644 index 0000000000000..53272abccbbf0 --- /dev/null +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -0,0 +1,18 @@ +error[E0599]: no function or associated item named `deserialize` found for struct `A` in the current scope + --> $DIR/issue-87932.rs:13:8 + | +LL | pub struct A {} + | ------------ function or associated item `deserialize` not found for this +... +LL | A::deserialize(); + | ^^^^^^^^^^^ function or associated item not found in `A` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use ::deserialize::_a::Deserialize; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`.