From d1e337bded30b84df777f6de3d8fc588286f0834 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Wed, 24 Oct 2018 01:03:47 +0300
Subject: [PATCH] Prohibit macro-expanded `extern crate` items shadowing crates
 passed with `--extern`

---
 src/librustc_resolve/build_reduced_graph.rs     | 17 +++++++++++++++--
 .../feature-gate-extern_crate_item_prelude.rs   |  7 +++++++
 ...eature-gate-extern_crate_item_prelude.stderr | 10 +++++++++-
 .../imports/extern-prelude-extern-crate-fail.rs |  9 +++++++++
 .../extern-prelude-extern-crate-fail.stderr     | 13 +++++++++++--
 5 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 777a5ab79d090..aa7bfeae5f48b 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -446,10 +446,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
                 if ptr::eq(self.current_module, self.graph_root) {
-                    self.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry {
+                    if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
+                        if expansion != Mark::root() && orig_name.is_some() &&
+                           entry.extern_crate_item.is_none() {
+                            self.session.span_err(item.span, "macro-expanded `extern crate` items \
+                                                              cannot shadow names passed with \
+                                                              `--extern`");
+                        }
+                    }
+                    let entry = self.extern_prelude.entry(ident.modern())
+                                                   .or_insert(ExternPreludeEntry {
                         extern_crate_item: None,
                         introduced_by_item: true,
-                    }).extern_crate_item = Some(binding);
+                    });
+                    entry.extern_crate_item = Some(binding);
+                    if orig_name.is_some() {
+                        entry.introduced_by_item = true;
+                    }
                 }
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
                     root_id: item.id,
diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs
index eb7c52c3d0f32..a043b6c2e6107 100644
--- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs
+++ b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs
@@ -36,4 +36,11 @@ mod import_absolute {
     //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
 }
 
+extern crate alloc as core;
+
+mod unrelated_crate_renamed {
+    type A = core::boxed::Box<u8>;
+    //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable
+}
+
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr
index 4dec8a35bcab1..cabfb56d7a840 100644
--- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr
+++ b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr
@@ -62,6 +62,14 @@ LL |         type A = ::alloc::boxed::Box<u8>;
    |
    = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
 
-error: aborting due to 8 previous errors
+error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658)
+  --> $DIR/feature-gate-extern_crate_item_prelude.rs:42:14
+   |
+LL |     type A = core::boxed::Box<u8>;
+   |              ^^^^
+   |
+   = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.rs b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs
index 22248af6d3a2d..57b097c9df318 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-fail.rs
+++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.rs
@@ -1,4 +1,5 @@
 // aux-build:two_macros.rs
+// compile-flags:--extern non_existent
 
 mod n {
     extern crate two_macros;
@@ -10,4 +11,12 @@ mod m {
     }
 }
 
+macro_rules! define_std_as_non_existent {
+    () => {
+        extern crate std as non_existent;
+        //~^ ERROR `extern crate` items cannot shadow names passed with `--extern`
+    }
+}
+define_std_as_non_existent!();
+
 fn main() {}
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
index 464812f1f6902..8f68d2af34ca3 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
+++ b/src/test/ui/imports/extern-prelude-extern-crate-fail.stderr
@@ -1,9 +1,18 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/extern-prelude-extern-crate-fail.rs:16:9
+   |
+LL |         extern crate std as non_existent;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | define_std_as_non_existent!();
+   | ------------------------------ in this macro invocation
+
 error[E0433]: failed to resolve. Use of undeclared type or module `two_macros`
-  --> $DIR/extern-prelude-extern-crate-fail.rs:9:9
+  --> $DIR/extern-prelude-extern-crate-fail.rs:10:9
    |
 LL |         two_macros::m!(); //~ ERROR failed to resolve. Use of undeclared type or module `two_macros`
    |         ^^^^^^^^^^ Use of undeclared type or module `two_macros`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.