Add test for serializing hygiene *into* a proc-macro crate
This is a very obscure corner case, and should never be hit in practice.
This commit is contained in:
parent
5cd1b5dd79
commit
979dd77c5d
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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!();
|
||||
}
|
||||
|
@ -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)
|
||||
*/
|
||||
|
@ -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 []
|
||||
|
Loading…
x
Reference in New Issue
Block a user