Skip to content

Commit a5764de

Browse files
committed
expand: Stop using nonterminals for passing tokens to attribute and derive macros
1 parent d462551 commit a5764de

26 files changed

+118
-88
lines changed

src/librustc_ast/token.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::tokenstream::TokenTree;
1111
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1212
use rustc_data_structures::sync::Lrc;
1313
use rustc_macros::HashStable_Generic;
14-
use rustc_span::symbol::kw;
14+
use rustc_span::symbol::{kw, sym};
1515
use rustc_span::symbol::{Ident, Symbol};
1616
use rustc_span::{self, Span, DUMMY_SP};
1717
use std::borrow::Cow;
@@ -785,6 +785,26 @@ impl Nonterminal {
785785
NtTT(tt) => tt.span(),
786786
}
787787
}
788+
789+
/// This nonterminal looks like some specific enums from
790+
/// `proc-macro-hack` and `procedural-masquerade` crates.
791+
/// We need to maintain some special pretty-printing behavior for them due to incorrect
792+
/// asserts in old versions of those crates and their wide use in the ecosystem.
793+
/// See issue #73345 for more details.
794+
/// FIXME: Remove this eventually.
795+
pub fn pretty_printing_compatibility_hack(&self) -> bool {
796+
if let NtItem(item) = self {
797+
let name = item.ident.name;
798+
if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
799+
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
800+
if let [variant] = &*enum_def.variants {
801+
return variant.ident.name == sym::Input;
802+
}
803+
}
804+
}
805+
}
806+
false
807+
}
788808
}
789809

790810
impl PartialEq for Nonterminal {

src/librustc_ast_pretty/pprust.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,14 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
148148
printer.s.eof()
149149
}
150150

151-
// This makes comma-separated lists look slightly nicer,
152-
// and also addresses a specific regression described in issue #63896.
151+
// This makes printed token streams look slightly nicer,
152+
// and also addresses some specific regressions described in #63896 and #73345.
153153
fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
154+
if let TokenTree::Token(token) = prev {
155+
if let token::DocComment(s) = token.kind {
156+
return !s.as_str().starts_with("//");
157+
}
158+
}
154159
match tt {
155160
TokenTree::Token(token) => match token.kind {
156161
token::Comma => false,
@@ -163,7 +168,14 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
163168
},
164169
_ => true,
165170
},
166-
_ => true,
171+
TokenTree::Delimited(_, DelimToken::Bracket, _) => match prev {
172+
TokenTree::Token(token) => match token.kind {
173+
token::Pound => false,
174+
_ => true,
175+
},
176+
_ => true,
177+
},
178+
TokenTree::Delimited(..) => true,
167179
}
168180
}
169181

src/librustc_expand/base.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use crate::module::DirectoryOwnership;
44
use rustc_ast::ast::{self, Attribute, NodeId, PatKind};
55
use rustc_ast::mut_visit::{self, MutVisitor};
66
use rustc_ast::ptr::P;
7-
use rustc_ast::token::{self, FlattenGroup};
8-
use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
7+
use rustc_ast::token;
8+
use rustc_ast::tokenstream::{self, TokenStream};
99
use rustc_ast::visit::{AssocCtxt, Visitor};
1010
use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
1111
use rustc_data_structures::fx::FxHashMap;
1212
use rustc_data_structures::sync::{self, Lrc};
1313
use rustc_errors::{DiagnosticBuilder, ErrorReported};
14-
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
14+
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
1515
use rustc_session::{parse::ParseSess, Limit};
1616
use rustc_span::def_id::DefId;
1717
use rustc_span::edition::Edition;
@@ -120,10 +120,7 @@ impl Annotatable {
120120
}
121121
}
122122

123-
crate fn into_tokens(self) -> TokenStream {
124-
// `Annotatable` can be converted into tokens directly, but we
125-
// are packing it into a nonterminal as a piece of AST to make
126-
// the produced token stream look nicer in pretty-printed form.
123+
crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
127124
let nt = match self {
128125
Annotatable::Item(item) => token::NtItem(item),
129126
Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => {
@@ -142,7 +139,7 @@ impl Annotatable {
142139
| Annotatable::StructField(..)
143140
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
144141
};
145-
TokenTree::token(token::Interpolated(Lrc::new(nt), FlattenGroup::Yes), DUMMY_SP).into()
142+
nt_to_tokenstream(&nt, sess, DUMMY_SP)
146143
}
147144

148145
pub fn expect_item(self) -> P<ast::Item> {

src/librustc_expand/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
705705
SyntaxExtensionKind::Attr(expander) => {
706706
self.gate_proc_macro_input(&item);
707707
self.gate_proc_macro_attr_item(span, &item);
708-
let tokens = item.into_tokens();
708+
let tokens = item.into_tokens(self.cx.parse_sess);
709709
let attr_item = attr.unwrap_normal_item();
710710
if let MacArgs::Eq(..) = attr_item.args {
711711
self.cx.span_err(span, "key-value macro attributes are not supported");

src/librustc_expand/proc_macro.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use crate::proc_macro_server;
33

44
use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem};
55
use rustc_ast::token::{self, FlattenGroup};
6-
use rustc_ast::tokenstream::{self, TokenStream};
6+
use rustc_ast::tokenstream::{TokenStream, TokenTree};
77
use rustc_data_structures::sync::Lrc;
88
use rustc_errors::{Applicability, ErrorReported};
9+
use rustc_parse::nt_to_tokenstream;
910
use rustc_span::symbol::sym;
1011
use rustc_span::{Span, DUMMY_SP};
1112

@@ -102,8 +103,13 @@ impl MultiItemModifier for ProcMacroDerive {
102103
}
103104
}
104105

105-
let token = token::Interpolated(Lrc::new(token::NtItem(item)), FlattenGroup::Yes);
106-
let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
106+
let item = token::NtItem(item);
107+
let input = if item.pretty_printing_compatibility_hack() {
108+
TokenTree::token(token::Interpolated(Lrc::new(item), FlattenGroup::Yes), DUMMY_SP)
109+
.into()
110+
} else {
111+
nt_to_tokenstream(&item, ecx.parse_sess, DUMMY_SP)
112+
};
107113

108114
let server = proc_macro_server::Rustc::new(ecx);
109115
let stream = match self.client.run(&EXEC_STRATEGY, server, input) {

src/librustc_expand/proc_macro_server.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,17 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
180180
tt!(Punct::new('#', false))
181181
}
182182

183-
Interpolated(nt, flatten) => {
183+
Interpolated(nt, _) => {
184184
let stream = nt_to_tokenstream(&nt, sess, span);
185185
TokenTree::Group(Group {
186186
delimiter: Delimiter::None,
187187
stream,
188188
span: DelimSpan::from_single(span),
189-
flatten,
189+
flatten: if nt.pretty_printing_compatibility_hack() {
190+
FlattenGroup::Yes
191+
} else {
192+
FlattenGroup::No
193+
},
190194
})
191195
}
192196

src/librustc_span/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ symbols! {
401401
infer_outlives_requirements,
402402
infer_static_outlives_requirements,
403403
inline,
404+
Input,
404405
intel,
405406
into_iter,
406407
IntoIterator,
@@ -588,6 +589,8 @@ symbols! {
588589
proc_macro_mod,
589590
proc_macro_non_items,
590591
proc_macro_path_invoc,
592+
ProceduralMasqueradeDummyType,
593+
ProcMacroHack,
591594
profiler_builtins,
592595
profiler_runtime,
593596
ptr_guaranteed_eq,

src/test/run-make/rustc-macro-dep-files/foo.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ use proc_macro::TokenStream;
77
#[proc_macro_derive(A)]
88
pub fn derive(input: TokenStream) -> TokenStream {
99
let input = input.to_string();
10-
assert!(input.contains("struct A;"));
10+
assert!(input.contains("struct A ;"));
1111
"struct B;".parse().unwrap()
1212
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
async fn f(mut x: u8) { }
2-
async fn g((mut x, y, mut z): (u8, u8, u8)) { }
3-
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { }
1+
async fn f(mut x : u8) { }
2+
async fn g((mut x, y, mut z) : (u8, u8, u8)) { }
3+
async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) { }

src/test/ui/proc-macro/auxiliary/attr-cfg.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@ use proc_macro::TokenStream;
1111
pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream {
1212
let input_str = input.to_string();
1313

14-
assert_eq!(input_str, "fn outer() -> u8 {
15-
#[cfg(foo)]
16-
fn inner() -> u8 { 1 }
17-
#[cfg(bar)]
18-
fn inner() -> u8 { 2 }
14+
assert_eq!(input_str, "fn outer() -> u8
15+
{
16+
#[cfg(foo)] fn inner() -> u8 { 1 } #[cfg(bar)] fn inner() -> u8 { 2 }
1917
inner()
2018
}");
2119

src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use proc_macro::TokenStream;
1010
#[proc_macro_attribute]
1111
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
1212
assert!(attr.to_string().is_empty());
13-
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
13+
assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
1414
item
1515
}
1616

1717
#[proc_macro_attribute]
1818
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
1919
assert!(attr.to_string().is_empty());
20-
assert_eq!(item.to_string(), "println!(\"{}\", string);");
20+
assert_eq!(item.to_string(), "println ! (\"{}\", string) ;");
2121
item
2222
}
2323

@@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
3131
#[proc_macro_attribute]
3232
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
3333
assert!(attr.to_string().is_empty());
34-
assert_eq!(item.to_string(), "println!(\"{}\", string)");
34+
assert_eq!(item.to_string(), "println ! (\"{}\", string)");
3535
item
3636
}
3737

src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use proc_macro::TokenStream;
1010
#[proc_macro_attribute]
1111
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
1212
assert!(attr.to_string().is_empty());
13-
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
13+
assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
1414
item
1515
}
1616

1717
#[proc_macro_attribute]
1818
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
1919
assert!(attr.to_string().is_empty());
20-
assert_eq!(item.to_string(), "println!(\"{}\", string);");
20+
assert_eq!(item.to_string(), "println ! (\"{}\", string) ;");
2121
item
2222
}
2323

@@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
3131
#[proc_macro_attribute]
3232
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
3333
assert!(attr.to_string().is_empty());
34-
assert_eq!(item.to_string(), "println!(\"{}\", string)");
34+
assert_eq!(item.to_string(), "println ! (\"{}\", string)");
3535
item
3636
}
3737

src/test/ui/proc-macro/auxiliary/derive-a.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(A)]
1111
pub fn derive(input: TokenStream) -> TokenStream {
1212
let input = input.to_string();
13-
assert!(input.contains("struct A;"));
13+
assert!(input.contains("struct A ;"));
1414
"".parse().unwrap()
1515
}

src/test/ui/proc-macro/auxiliary/derive-atob.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(AToB)]
1111
pub fn derive(input: TokenStream) -> TokenStream {
1212
let input = input.to_string();
13-
assert_eq!(input, "struct A;");
13+
assert_eq!(input, "struct A ;");
1414
"struct B;".parse().unwrap()
1515
}

src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(B, attributes(B, C))]
1111
pub fn derive(input: TokenStream) -> TokenStream {
1212
let input = input.to_string();
13-
assert!(input.contains("#[B[arbitrary tokens]]"));
13+
assert!(input.contains("#[B [arbitrary tokens]]"));
1414
assert!(input.contains("struct B {"));
1515
assert!(input.contains("#[C]"));
1616
"".parse().unwrap()

src/test/ui/proc-macro/auxiliary/derive-ctod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(CToD)]
1111
pub fn derive(input: TokenStream) -> TokenStream {
1212
let input = input.to_string();
13-
assert_eq!(input, "struct C;");
13+
assert_eq!(input, "struct C ;");
1414
"struct D;".parse().unwrap()
1515
}

src/test/ui/proc-macro/auxiliary/derive-same-struct.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ use proc_macro::TokenStream;
1010
#[proc_macro_derive(AToB)]
1111
pub fn derive1(input: TokenStream) -> TokenStream {
1212
println!("input1: {:?}", input.to_string());
13-
assert_eq!(input.to_string(), "struct A;");
13+
assert_eq!(input.to_string(), "struct A ;");
1414
"#[derive(BToC)] struct B;".parse().unwrap()
1515
}
1616

1717
#[proc_macro_derive(BToC)]
1818
pub fn derive2(input: TokenStream) -> TokenStream {
19-
assert_eq!(input.to_string(), "struct B;");
19+
assert_eq!(input.to_string(), "struct B ;");
2020
"struct C;".parse().unwrap()
2121
}

src/test/ui/proc-macro/auxiliary/derive-union.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn derive(input: TokenStream) -> TokenStream {
1212
let input = input.to_string();
1313
assert!(input.contains("#[repr(C)]"));
1414
assert!(input.contains("union Test {"));
15-
assert!(input.contains("a: u8,"));
15+
assert!(input.contains("a : u8,"));
1616
assert!(input.contains("}"));
1717
"".parse().unwrap()
1818
}
+4-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
// force-host
22
// no-prefer-dynamic
33

4+
#![feature(proc_macro_quote)]
5+
46
#![crate_type = "proc-macro"]
57

68
extern crate proc_macro;
7-
8-
use proc_macro::TokenStream;
9+
use proc_macro::*;
910

1011
// Outputs another copy of the struct. Useful for testing the tokens
1112
// seen by the proc_macro.
1213
#[proc_macro_derive(Double)]
1314
pub fn derive(input: TokenStream) -> TokenStream {
14-
format!("mod foo {{ {} }}", input.to_string()).parse().unwrap()
15+
quote!(mod foo { $input })
1516
}

src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use proc_macro::TokenStream;
1111
#[proc_macro_derive(A)]
1212
pub fn derive(input: TokenStream) -> TokenStream {
1313
let input = input.to_string();
14-
assert!(input.contains("struct A;"));
14+
assert!(input.contains("struct A ;"));
1515
r#"
1616
impl A {
1717
fn a(&self) {
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
input1: "struct A;"
1+
input1: "struct A ;"

src/test/ui/proc-macro/dollar-crate-issue-57089.stdout

+1-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
3838
span: #3 bytes(LO..HI),
3939
},
4040
]
41-
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
42-
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
41+
PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
4342
PRINT-ATTR INPUT (DEBUG): TokenStream [
4443
Ident {
4544
ident: "struct",

src/test/ui/proc-macro/dollar-crate-issue-62325.stdout

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
2-
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ;
1+
PRINT-ATTR INPUT (DISPLAY): struct A(identity ! ($crate :: S)) ;
32
PRINT-ATTR INPUT (DEBUG): TokenStream [
43
Ident {
54
ident: "struct",
@@ -54,8 +53,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
5453
span: #3 bytes(LO..HI),
5554
},
5655
]
57-
PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
58-
PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ;
56+
PRINT-ATTR INPUT (DISPLAY): struct B(identity ! ($crate :: S)) ;
5957
PRINT-ATTR INPUT (DEBUG): TokenStream [
6058
Ident {
6159
ident: "struct",

0 commit comments

Comments
 (0)