about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-06 19:45:23 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-11 00:12:08 +0300
commit0ec6ea7333a8918a96f40110e014f2bbbd72281f (patch)
treef74a3a467a2314be5d1d10237289a4f19d3612d2
parentf92394209455bf14594f279249c2e592809180cd (diff)
downloadrust-0ec6ea7333a8918a96f40110e014f2bbbd72281f.tar.gz
rust-0ec6ea7333a8918a96f40110e014f2bbbd72281f.zip
resolve: Fix access to extern and stdlib prelude from opaque macros
Ok, it's hard to explain what happens, but identifier's hygienic contexts need to be "adjusted" to modules/scopes before they are resolved in them.
To be resolved in all kinds on preludes the identifier needs to be adjusted to the root expansion (aka "no expansion").

Previously this was done for the `macro m() { ::my_crate::foo }` case, but forgotten for all other cases.
-rw-r--r--src/librustc_resolve/lib.rs1
-rw-r--r--src/librustc_resolve/macros.rs1
-rw-r--r--src/test/ui/hygiene/auxiliary/stdlib-prelude.rs3
-rw-r--r--src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs21
-rw-r--r--src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs16
5 files changed, 42 insertions, 0 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 795ff3faffa..1216a083700 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2247,6 +2247,7 @@ impl<'a> Resolver<'a> {
         }
 
         if !module.no_implicit_prelude {
+            ident.span.adjust(Mark::root());
             if ns == TypeNS {
                 if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
                     return Some(LexicalScopeBinding::Item(binding));
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 077c126bdee..7ad54d572f4 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -856,6 +856,7 @@ impl<'a> Resolver<'a> {
                     match self.hygienic_lexical_parent(module, &mut ident.span) {
                         Some(parent_module) => WhereToResolve::Module(parent_module),
                         None => {
+                            ident.span.adjust(Mark::root());
                             use_prelude = !module.no_implicit_prelude;
                             match ns {
                                 TypeNS => WhereToResolve::ExternPrelude,
diff --git a/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs b/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs
new file mode 100644
index 00000000000..81b0b7faa5b
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs
@@ -0,0 +1,3 @@
+#![feature(decl_macro)]
+
+pub macro stdlib_macro() {}
diff --git a/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs b/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs
new file mode 100644
index 00000000000..c8c5c72bf95
--- /dev/null
+++ b/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs
@@ -0,0 +1,21 @@
+// check-pass
+// aux-build:stdlib-prelude.rs
+
+#![feature(decl_macro)]
+#![feature(prelude_import)]
+
+extern crate stdlib_prelude;
+
+#[prelude_import]
+use stdlib_prelude::*;
+
+macro mac() {
+    mod m {
+        use std::mem; // OK (extern prelude)
+        stdlib_macro!(); // OK (stdlib prelude)
+    }
+}
+
+mac!();
+
+fn main() {}
diff --git a/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs
new file mode 100644
index 00000000000..cf65de2bc23
--- /dev/null
+++ b/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(decl_macro)]
+
+macro mac() {
+    mod m {
+        fn f() {
+            std::mem::drop(0); // OK (extern prelude)
+            drop(0); // OK (stdlib prelude)
+        }
+    }
+}
+
+mac!();
+
+fn main() {}