Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 979dd77

Browse files
committed
Add test for serializing hygiene *into* a proc-macro crate
This is a very obscure corner case, and should never be hit in practice.
1 parent 5cd1b5d commit 979dd77

File tree

6 files changed

+88
-16
lines changed

6 files changed

+88
-16
lines changed

src/librustc_metadata/rmeta/encoder.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,33 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
259259
let len = hi - lo;
260260
len.encode(self)?;
261261

262-
// FIXME: Once #69976 is merged, treat proc-macros normally
263-
// Currently, we can't encode `SyntaxContextData` for proc-macro crates,
264-
// since the `SyntaxContextData`/`ExpnData` might reference `DefIds` from
265-
// dependencies (which are not currently loaded during decoding).
262+
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
263+
// since we don't load proc-macro dependencies during serialization.
264+
// This means that any hygiene information from macros used *within*
265+
// a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
266+
// definition) will be lost.
267+
//
268+
// This can show up in two ways:
269+
//
270+
// 1. Any hygiene information associated with identifier of
271+
// a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
272+
// Since proc-macros can only be invoked from a different crate,
273+
// real code should never need to care about this.
274+
//
275+
// 2. Using `Span::def_site` or `Span::mixed_site` will not
276+
// include any hygiene information associated with the defintion
277+
// site. This means that a proc-macro cannot emit a `$crate`
278+
// identifier which resolves to one of its dependencies,
279+
// which also should never come up in practice.
280+
//
281+
// Additionally, this affects `Span::parent`, and any other
282+
// span inspection APIs that would otherwise allow traversing
283+
// the `SyntaxContexts` associated with a span.
284+
//
285+
// None of these user-visible effects should result in any
286+
// cross-crate inconsistencies (getting one behavior in the same
287+
// crate, and a different behavior in another crate) due to the
288+
// limited surface that proc-macros can expose.
266289
if self.is_proc_macro {
267290
SyntaxContext::root().encode(self)?;
268291
} else {

src/test/ui/proc-macro/auxiliary/make-macro.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ macro_rules! make_it {
66
#[proc_macro]
77
pub fn $name(input: TokenStream) -> TokenStream {
88
println!("Def site: {:?}", Span::def_site());
9-
input
9+
println!("Input: {:?}", input);
10+
let new: TokenStream = input.into_iter().map(|mut t| {
11+
t.set_span(Span::def_site());
12+
t
13+
}).collect();
14+
println!("Respanned: {:?}", new);
15+
new
1016
}
1117
};
1218
}

src/test/ui/proc-macro/auxiliary/meta-macro.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ extern crate make_macro;
1010
use proc_macro::{TokenStream, Span};
1111

1212
make_macro::make_it!(print_def_site);
13+
14+
#[proc_macro]
15+
pub fn dummy(input: TokenStream) -> TokenStream { input }
Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
// aux-build:make-macro.rs
22
// aux-build:meta-macro.rs
33
// edition:2018
4-
// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
4+
// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene -Z macro-backtrace
55
// check-pass
66
// normalize-stdout-test "\d+#" -> "0#"
7-
// ^ We don't care about symbol ids, so set them all to 0
7+
//
8+
// We don't care about symbol ids, so we set them all to 0
89
// in the stdout
910
extern crate meta_macro;
11+
extern crate make_macro;
12+
13+
macro_rules! produce_it {
14+
() => {
15+
// `print_def_site!` will respan the `$crate` identifier
16+
// with `Span::def_site()`. This should cause it to resolve
17+
// relative to `meta_macro`, *not* `make_macro` (despite
18+
// the fact that that `print_def_site` is produced by
19+
// a `macro_rules!` macro in `make_macro`).
20+
meta_macro::print_def_site!($crate::dummy!());
21+
}
22+
}
1023

1124
fn main() {
12-
meta_macro::print_def_site!();
25+
produce_it!();
1326
}
Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#6)
1+
Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#7)
2+
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) }]
3+
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) }]
24
#![feature /* 0#0 */(prelude_import)]
35
#[prelude_import /* 0#1 */]
46
use std /* 0#1 */::prelude /* 0#1 */::v1 /* 0#1 */::*;
@@ -7,24 +9,43 @@ extern crate std /* 0#1 */;
79
// aux-build:make-macro.rs
810
// aux-build:meta-macro.rs
911
// edition:2018
10-
// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
12+
// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene -Z macro-backtrace
1113
// check-pass
1214
// normalize-stdout-test "\d+#" -> "0#"
13-
// ^ We don't care about symbol ids, so set them all to 0
15+
//
16+
// We don't care about symbol ids, so we set them all to 0
1417
// in the stdout
1518
extern crate meta_macro /* 0#0 */;
19+
extern crate make_macro /* 0#0 */;
20+
21+
macro_rules! produce_it
22+
/*
23+
0#0
24+
*/ {
25+
() =>
26+
{
27+
meta_macro :: print_def_site ! ($ crate :: dummy ! ()) ;
28+
// `print_def_site!` will respan the `$crate` identifier
29+
// with `Span::def_site()`. This should cause it to resolve
30+
// relative to `meta_macro`, *not* `make_macro` (despite
31+
// the fact that that `print_def_site` is produced by
32+
// a `macro_rules!` macro in `make_macro`).
33+
}
34+
}
1635

1736
fn main /* 0#0 */() { }
1837

1938
/*
2039
Expansions:
2140
0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
2241
1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
23-
2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
42+
2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
2443
3: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "cfg_if")
2544
4: parent: ExpnId(3), call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "$crate::cfg_if")
2645
5: parent: ExpnId(4), call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::cfg_if")
2746
6: parent: ExpnId(5), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "features")
47+
7: parent: ExpnId(2), call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
48+
8: parent: ExpnId(7), call_site_ctxt: #7, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
2849

2950
SyntaxContexts:
3051
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
@@ -33,7 +54,11 @@ SyntaxContexts:
3354
#3: parent: #0, outer_mark: (ExpnId(6), SemiTransparent)
3455
#4: parent: #0, outer_mark: (ExpnId(3), SemiTransparent)
3556
#5: parent: #0, outer_mark: (ExpnId(4), SemiTransparent)
36-
#6: parent: #0, outer_mark: (ExpnId(2), Opaque)
37-
#7: parent: #0, outer_mark: (ExpnId(2), Transparent)
38-
#8: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
57+
#6: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
58+
#7: parent: #0, outer_mark: (ExpnId(7), Opaque)
59+
#8: parent: #6, outer_mark: (ExpnId(7), Transparent)
60+
#9: parent: #0, outer_mark: (ExpnId(7), SemiTransparent)
61+
#10: parent: #0, outer_mark: (ExpnId(8), Opaque)
62+
#11: parent: #7, outer_mark: (ExpnId(8), Transparent)
63+
#12: parent: #7, outer_mark: (ExpnId(8), SemiTransparent)
3964
*/
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#6)
1+
Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#6)
2+
Input: TokenStream []
3+
Respanned: TokenStream []

0 commit comments

Comments
 (0)