about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-06-29 03:45:47 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-06-30 01:53:32 +0300
commitb69d51162b5391119e86d1c6e884aa09292a7806 (patch)
tree7130f277aa610ff99c5de9f51b190153d097ca28
parent9f92fce77c74cf3c47035e9ff69c29daee0517b3 (diff)
downloadrust-b69d51162b5391119e86d1c6e884aa09292a7806.tar.gz
rust-b69d51162b5391119e86d1c6e884aa09292a7806.zip
Restore the old behavior of `$crate` in nested `macro_rules`
`$crate` is not resolved at def-site of a macro, but rather at "transitive def-site"
-rw-r--r--src/librustc_resolve/lib.rs26
-rw-r--r--src/test/ui/hygiene/auxiliary/intercrate.rs31
-rw-r--r--src/test/ui/hygiene/dollar-crate-modern.rs19
3 files changed, 71 insertions, 5 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 9887abd60bf..9475b96d30b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1989,7 +1989,31 @@ impl<'a> Resolver<'a> {
             // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
             // we don't want to pretend that the `macro_rules!` definition is in the `macro`
             // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
-            ctxt.marks().into_iter().rev().find(|m| m.transparency() != Transparency::Transparent)
+            // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
+            // definitions actually produced by `macro` and `macro` definitions produced by
+            // `macro_rules!`, but at least such configurations are not stable yet.
+            ctxt = ctxt.modern_and_legacy();
+            let mut iter = ctxt.marks().into_iter().rev().peekable();
+            let mut result = None;
+            // Find the last modern mark from the end if it exists.
+            while let Some(&mark) = iter.peek() {
+                if mark.transparency() == Transparency::Opaque {
+                    result = Some(mark);
+                    iter.next();
+                } else {
+                    break;
+                }
+            }
+            // Then find the last legacy mark from the end if it exists.
+            while let Some(&mark) = iter.peek() {
+                if mark.transparency() == Transparency::SemiTransparent {
+                    result = Some(mark);
+                    iter.next();
+                } else {
+                    break;
+                }
+            }
+            result
         } else {
             ctxt = ctxt.modern();
             ctxt.adjust(Mark::root())
diff --git a/src/test/ui/hygiene/auxiliary/intercrate.rs b/src/test/ui/hygiene/auxiliary/intercrate.rs
index 244a9903e31..f917fabbe0c 100644
--- a/src/test/ui/hygiene/auxiliary/intercrate.rs
+++ b/src/test/ui/hygiene/auxiliary/intercrate.rs
@@ -22,6 +22,35 @@ pub mod foo {
 
 pub struct SomeType;
 
-pub macro uses_dollar_crate() {
+// `$crate`
+pub macro uses_dollar_crate_modern() {
     type Alias = $crate::SomeType;
 }
+
+pub macro define_uses_dollar_crate_modern_nested($uses_dollar_crate_modern_nested: ident) {
+    macro $uses_dollar_crate_modern_nested() {
+        type AliasCrateModernNested = $crate::SomeType;
+    }
+}
+
+#[macro_export]
+macro_rules! define_uses_dollar_crate_legacy_nested {
+    () => {
+        macro_rules! uses_dollar_crate_legacy_nested {
+            () => {
+                type AliasLegacyNested = $crate::SomeType;
+            }
+        }
+    }
+}
+
+// `crate`
+pub macro uses_crate_modern() {
+    type AliasCrate = crate::SomeType;
+}
+
+pub macro define_uses_crate_modern_nested($uses_crate_modern_nested: ident) {
+    macro $uses_crate_modern_nested() {
+        type AliasCrateModernNested = crate::SomeType;
+    }
+}
diff --git a/src/test/ui/hygiene/dollar-crate-modern.rs b/src/test/ui/hygiene/dollar-crate-modern.rs
index f4b24d0c5b4..6e536ab1422 100644
--- a/src/test/ui/hygiene/dollar-crate-modern.rs
+++ b/src/test/ui/hygiene/dollar-crate-modern.rs
@@ -8,15 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Make sure `$crate` works in `macro` macros.
+// Make sure `$crate` and `crate` work in for basic cases of nested macros.
 
 // compile-pass
 // aux-build:intercrate.rs
 
-#![feature(use_extern_macros)]
+#![feature(decl_macro, crate_in_paths)]
 
 extern crate intercrate;
 
-intercrate::uses_dollar_crate!();
+// `$crate`
+intercrate::uses_dollar_crate_modern!();
+
+intercrate::define_uses_dollar_crate_modern_nested!(uses_dollar_crate_modern_nested);
+uses_dollar_crate_modern_nested!();
+
+intercrate::define_uses_dollar_crate_legacy_nested!();
+uses_dollar_crate_legacy_nested!();
+
+// `crate`
+intercrate::uses_crate_modern!();
+
+intercrate::define_uses_crate_modern_nested!(uses_crate_modern_nested);
+uses_crate_modern_nested!();
 
 fn main() {}