about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2020-07-21 19:51:07 -0400
committerAaron Hill <aa1ronham@gmail.com>2020-07-26 18:37:02 -0400
commit979dd77c5d88cd21f350da5235d198b97264ec68 (patch)
tree0496b44557f2392a30c6e66386d7b49623680e8f
parent5cd1b5dd7972e465bb7d7f6fbfecae6b6f6c299d (diff)
downloadrust-979dd77c5d88cd21f350da5235d198b97264ec68.tar.gz
rust-979dd77c5d88cd21f350da5235d198b97264ec68.zip
Add test for serializing hygiene *into* a proc-macro crate
This is a very obscure corner case, and should never be hit in practice.
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs31
-rw-r--r--src/test/ui/proc-macro/auxiliary/make-macro.rs8
-rw-r--r--src/test/ui/proc-macro/auxiliary/meta-macro.rs3
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.rs19
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.stdout39
-rw-r--r--src/test/ui/proc-macro/meta-macro.stdout4
6 files changed, 88 insertions, 16 deletions
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 6539c13d812..076ed679834 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -259,10 +259,33 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
         let len = hi - lo;
         len.encode(self)?;
 
-        // FIXME: Once #69976 is merged, treat proc-macros normally
-        // Currently, we can't encode `SyntaxContextData` for proc-macro crates,
-        // since the `SyntaxContextData`/`ExpnData` might reference `DefIds` from
-        // dependencies (which are not currently loaded during decoding).
+        // Don't serialize any `SyntaxContext`s from a proc-macro crate,
+        // since we don't load proc-macro dependencies during serialization.
+        // This means that any hygiene information from macros used *within*
+        // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
+        // definition) will be lost.
+        //
+        // This can show up in two ways:
+        //
+        // 1. Any hygiene information associated with identifier of
+        // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
+        // Since proc-macros can only be invoked from a different crate,
+        // real code should never need to care about this.
+        //
+        // 2. Using `Span::def_site` or `Span::mixed_site` will not
+        // include any hygiene information associated with the defintion
+        // site. This means that a proc-macro cannot emit a `$crate`
+        // identifier which resolves to one of its dependencies,
+        // which also should never come up in practice.
+        //
+        // Additionally, this affects `Span::parent`, and any other
+        // span inspection APIs that would otherwise allow traversing
+        // the `SyntaxContexts` associated with a span.
+        //
+        // None of these user-visible effects should result in any
+        // cross-crate inconsistencies (getting one behavior in the same
+        // crate, and a different behavior in another crate) due to the
+        // limited surface that proc-macros can expose.
         if self.is_proc_macro {
             SyntaxContext::root().encode(self)?;
         } else {
diff --git a/src/test/ui/proc-macro/auxiliary/make-macro.rs b/src/test/ui/proc-macro/auxiliary/make-macro.rs
index 2c21221fbb0..3c851b6de2a 100644
--- a/src/test/ui/proc-macro/auxiliary/make-macro.rs
+++ b/src/test/ui/proc-macro/auxiliary/make-macro.rs
@@ -6,7 +6,13 @@ macro_rules! make_it {
         #[proc_macro]
         pub fn $name(input: TokenStream) -> TokenStream {
             println!("Def site: {:?}", Span::def_site());
-            input
+            println!("Input: {:?}", input);
+            let new: TokenStream = input.into_iter().map(|mut t| {
+                t.set_span(Span::def_site());
+                t
+            }).collect();
+            println!("Respanned: {:?}", new);
+            new
         }
     };
 }
diff --git a/src/test/ui/proc-macro/auxiliary/meta-macro.rs b/src/test/ui/proc-macro/auxiliary/meta-macro.rs
index 5265c6533b4..0a9b9887d95 100644
--- a/src/test/ui/proc-macro/auxiliary/meta-macro.rs
+++ b/src/test/ui/proc-macro/auxiliary/meta-macro.rs
@@ -10,3 +10,6 @@ extern crate make_macro;
 use proc_macro::{TokenStream, Span};
 
 make_macro::make_it!(print_def_site);
+
+#[proc_macro]
+pub fn dummy(input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs
index 449377aed99..5e84be74da8 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.rs
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs
@@ -1,13 +1,26 @@
 // aux-build:make-macro.rs
 // aux-build:meta-macro.rs
 // edition:2018
-// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
+// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene -Z macro-backtrace
 // check-pass
 // normalize-stdout-test "\d+#" -> "0#"
-// ^ We don't care about symbol ids, so set them all to 0
+//
+// We don't care about symbol ids, so we set them all to 0
 // in the stdout
 extern crate meta_macro;
+extern crate make_macro;
+
+macro_rules! produce_it {
+    () => {
+        // `print_def_site!` will respan the `$crate` identifier
+        // with `Span::def_site()`. This should cause it to resolve
+        // relative to `meta_macro`, *not* `make_macro` (despite
+        // the fact that that `print_def_site` is produced by
+        // a `macro_rules!` macro in `make_macro`).
+        meta_macro::print_def_site!($crate::dummy!());
+    }
+}
 
 fn main() {
-    meta_macro::print_def_site!();
+    produce_it!();
 }
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
index 95f89b46d05..cb8ca614a23 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
@@ -1,4 +1,6 @@
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#6)
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7)
+Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:20:37: 20:43 (#6) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:20:43: 20:45 (#6) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:20:43: 20:45 (#6) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:20:45: 20:50 (#6) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:20:50: 20:51 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:20:51: 20:53 (#6) }]
+Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7) }]
 #![feature /* 0#0 */(prelude_import)]
 #[prelude_import /* 0#1 */]
 use std /* 0#1 */::prelude /* 0#1 */::v1 /* 0#1 */::*;
@@ -7,12 +9,29 @@ extern crate std /* 0#1 */;
 // aux-build:make-macro.rs
 // aux-build:meta-macro.rs
 // edition:2018
-// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
+// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene -Z macro-backtrace
 // check-pass
 // normalize-stdout-test "\d+#" -> "0#"
-// ^ We don't care about symbol ids, so set them all to 0
+//
+// We don't care about symbol ids, so we set them all to 0
 // in the stdout
 extern crate meta_macro /* 0#0 */;
+extern crate make_macro /* 0#0 */;
+
+macro_rules! produce_it
+    /*
+    0#0
+    */ {
+    () =>
+    {
+        meta_macro :: print_def_site ! ($ crate :: dummy ! ()) ;
+        // `print_def_site!` will respan the `$crate` identifier
+        // with `Span::def_site()`. This should cause it to resolve
+        // relative to `meta_macro`, *not* `make_macro` (despite
+        // the fact that that `print_def_site` is produced by
+        // a `macro_rules!` macro in `make_macro`).
+    }
+}
 
 fn main /* 0#0 */() { }
 
@@ -20,11 +39,13 @@ fn main /* 0#0 */() { }
 Expansions:
 0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
 1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
 3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "cfg_if")
 4: parent: ExpnId(3), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "$crate::cfg_if")
 5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::cfg_if")
 6: parent: ExpnId(5), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "features")
+7: parent: ExpnId(2), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+8: parent: ExpnId(7), call_site_ctxt: #7, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
 
 SyntaxContexts:
 #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
@@ -33,7 +54,11 @@ SyntaxContexts:
 #3: parent: #0, outer_mark: (ExpnId(6), SemiTransparent)
 #4: parent: #0, outer_mark: (ExpnId(3), SemiTransparent)
 #5: parent: #0, outer_mark: (ExpnId(4), SemiTransparent)
-#6: parent: #0, outer_mark: (ExpnId(2), Opaque)
-#7: parent: #0, outer_mark: (ExpnId(2), Transparent)
-#8: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
+#6: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
+#7: parent: #0, outer_mark: (ExpnId(7), Opaque)
+#8: parent: #6, outer_mark: (ExpnId(7), Transparent)
+#9: parent: #0, outer_mark: (ExpnId(7), SemiTransparent)
+#10: parent: #0, outer_mark: (ExpnId(8), Opaque)
+#11: parent: #7, outer_mark: (ExpnId(8), Transparent)
+#12: parent: #7, outer_mark: (ExpnId(8), SemiTransparent)
 */
diff --git a/src/test/ui/proc-macro/meta-macro.stdout b/src/test/ui/proc-macro/meta-macro.stdout
index 006c659df0b..e4374dbb3fa 100644
--- a/src/test/ui/proc-macro/meta-macro.stdout
+++ b/src/test/ui/proc-macro/meta-macro.stdout
@@ -1 +1,3 @@
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#6)
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#6)
+Input: TokenStream []
+Respanned: TokenStream []