Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b6be496

Browse files
committedFeb 29, 2020
Auto merge of #69594 - petrochenkov:nont3, r=<try>
[experiment] expand: Stop using nonterminals when passing items to proc macro attributes Implement the suggestion from #69423 (comment). r? @ghost
2 parents e9bca51 + 1968fd4 commit b6be496

File tree

12 files changed

+72
-81
lines changed

12 files changed

+72
-81
lines changed
 

‎src/librustc_expand/base.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
44
use rustc_data_structures::fx::FxHashMap;
55
use rustc_data_structures::sync::{self, Lrc};
66
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
7-
use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
7+
use rustc_parse::{self, nt_to_tokenstream, parser, DirectoryOwnership, MACRO_ARGUMENTS};
88
use rustc_session::parse::ParseSess;
99
use rustc_span::edition::Edition;
1010
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
@@ -118,6 +118,28 @@ impl Annotatable {
118118
}
119119
}
120120

121+
crate fn into_tokenstream(self, sess: &ParseSess) -> TokenStream {
122+
let span = self.span();
123+
let nt = match self {
124+
Annotatable::Item(item) => token::NtItem(item),
125+
Annotatable::TraitItem(item)
126+
| Annotatable::ImplItem(item)
127+
| Annotatable::ForeignItem(item) => {
128+
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
129+
}
130+
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
131+
Annotatable::Expr(expr) => token::NtExpr(expr),
132+
Annotatable::Arm(..)
133+
| Annotatable::Field(..)
134+
| Annotatable::FieldPat(..)
135+
| Annotatable::GenericParam(..)
136+
| Annotatable::Param(..)
137+
| Annotatable::StructField(..)
138+
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
139+
};
140+
nt_to_tokenstream(&nt, sess, span)
141+
}
142+
121143
pub fn expect_item(self) -> P<ast::Item> {
122144
match self {
123145
Annotatable::Item(i) => i,

‎src/librustc_expand/expand.rs

+3-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::proc_macro::collect_derives;
77

88
use rustc_ast_pretty::pprust;
99
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
10-
use rustc_data_structures::sync::Lrc;
1110
use rustc_errors::{Applicability, FatalError, PResult};
1211
use rustc_feature::Features;
1312
use rustc_parse::configure;
@@ -25,7 +24,7 @@ use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
2524
use syntax::mut_visit::*;
2625
use syntax::ptr::P;
2726
use syntax::token;
28-
use syntax::tokenstream::{TokenStream, TokenTree};
27+
use syntax::tokenstream::TokenStream;
2928
use syntax::util::map_in_place::MapInPlace;
3029
use syntax::visit::{self, AssocCtxt, Visitor};
3130

@@ -668,36 +667,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
668667
SyntaxExtensionKind::Attr(expander) => {
669668
self.gate_proc_macro_input(&item);
670669
self.gate_proc_macro_attr_item(span, &item);
671-
// `Annotatable` can be converted into tokens directly, but we are packing it
672-
// into a nonterminal as a piece of AST to make the produced token stream
673-
// look nicer in pretty-printed form. This may be no longer necessary.
674-
let item_tok = TokenTree::token(
675-
token::Interpolated(Lrc::new(match item {
676-
Annotatable::Item(item) => token::NtItem(item),
677-
Annotatable::TraitItem(item)
678-
| Annotatable::ImplItem(item)
679-
| Annotatable::ForeignItem(item) => {
680-
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
681-
}
682-
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
683-
Annotatable::Expr(expr) => token::NtExpr(expr),
684-
Annotatable::Arm(..)
685-
| Annotatable::Field(..)
686-
| Annotatable::FieldPat(..)
687-
| Annotatable::GenericParam(..)
688-
| Annotatable::Param(..)
689-
| Annotatable::StructField(..)
690-
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
691-
})),
692-
DUMMY_SP,
693-
)
694-
.into();
670+
let tokens = item.into_tokenstream(self.cx.parse_sess);
695671
let item = attr.unwrap_normal_item();
696672
if let MacArgs::Eq(..) = item.args {
697673
self.cx.span_err(span, "key-value macro attributes are not supported");
698674
}
699675
let tok_result =
700-
expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
676+
expander.expand(self.cx, span, item.args.inner_tokens(), tokens);
701677
self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
702678
}
703679
SyntaxExtensionKind::LegacyAttr(expander) => {
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-args.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {
1515

1616
let input = input.to_string();
1717

18-
assert_eq!(input, "fn foo() { }");
18+
assert_eq!(input, "fn foo () { }");
1919

2020
r#"
2121
fn foo() -> &'static str { "Hello, world!" }

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

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@ 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 }
19-
inner()
14+
assert_eq!(input_str, "fn outer () -> u8
15+
{
16+
# [cfg (foo)] fn inner () -> u8 { 1 } # [cfg (bar)] fn inner () -> u8
17+
{ 2 } inner ()
2018
}");
2119

2220
input

‎src/test/ui/proc-macro/auxiliary/attr-on-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
1010
#[proc_macro_attribute]
1111
pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream {
1212
drop(attr);
13-
assert_eq!(item.to_string(), "fn foo() { }");
13+
assert_eq!(item.to_string(), "fn foo () { }");
1414
"fn foo(&self);".parse().unwrap()
1515
}

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,28 @@ 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

2424
#[proc_macro_attribute]
2525
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
2626
assert!(attr.to_string().is_empty());
27-
assert_eq!(item.to_string(), "print_str(\"string\")");
27+
assert_eq!(item.to_string(), "print_str (\"string\")");
2828
item
2929
}
3030

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,28 @@ 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

2424
#[proc_macro_attribute]
2525
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
2626
assert!(attr.to_string().is_empty());
27-
assert_eq!(item.to_string(), "print_str(\"string\")");
27+
assert_eq!(item.to_string(), "print_str (\"string\")");
2828
item
2929
}
3030

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/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",

‎src/test/ui/proc-macro/dollar-crate.stdout

+2-4
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",
@@ -160,8 +159,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
160159
span: #13 bytes(LO..HI),
161160
},
162161
]
163-
PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
164-
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
162+
PRINT-ATTR INPUT (DISPLAY): struct A ($crate :: S) ;
165163
PRINT-ATTR INPUT (DEBUG): TokenStream [
166164
Ident {
167165
ident: "struct",

‎src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs

+24-24
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,28 @@ macro_rules! checker {
1717
}
1818
}
1919

20-
checker!(attr_extern, r#"extern "C" {
21-
fn ffi(#[a1] arg1: i32, #[a2] ...);
22-
}"#);
23-
checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) { }"#);
24-
checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);");
25-
checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }");
26-
checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }");
27-
checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }");
28-
checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }");
29-
checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) { }");
30-
checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) { }");
31-
checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);");
32-
checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);");
33-
checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);");
34-
checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);");
35-
checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);");
36-
checker!(rename_params, r#"impl Foo {
37-
fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) { }
38-
fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32,
39-
#[angery(true)] c: u32) {
40-
}
41-
fn hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32,
42-
#[what = "how"] b: i32, #[angery(true)] c: u32) {
43-
}
20+
checker!(attr_extern, r#"extern "C" { fn ffi (# [a1] arg1 : i32, # [a2] ...) ; }"#);
21+
checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar (arg1 : i32, # [a1] mut args : ...) { }"#);
22+
checker!(attr_alias, "type Alias = fn (# [a1] u8, # [a2] ...) ;");
23+
checker!(attr_free, "fn free (# [a1] arg1 : u8) { let lam = | # [a2] W (x), # [a3] y | () ; }");
24+
checker!(attr_inherent_1, "fn inherent1 (# [a1] self, # [a2] arg1 : u8) { }");
25+
checker!(attr_inherent_2, "fn inherent2 (# [a1] & self, # [a2] arg1 : u8) { }");
26+
checker!(attr_inherent_3, "fn inherent3 < 'a > (# [a1] & 'a mut self, # [a2] arg1 : u8) { }");
27+
checker!(attr_inherent_4, "fn inherent4 < 'a > (# [a1] self : Box < Self >, # [a2] arg1 : u8) { }");
28+
checker!(attr_inherent_issue_64682, "fn inherent5 (# [a1] # [a2] arg1 : u8, # [a3] arg2 : u8) { }");
29+
checker!(attr_trait_1, "fn trait1 (# [a1] self, # [a2] arg1 : u8) ;");
30+
checker!(attr_trait_2, "fn trait2 (# [a1] & self, # [a2] arg1 : u8) ;");
31+
checker!(attr_trait_3, "fn trait3 < 'a > (# [a1] & 'a mut self, # [a2] arg1 : u8) ;");
32+
checker!(attr_trait_4, r#"fn trait4 < 'a >
33+
(# [a1] self : Box < Self >, # [a2] arg1 : u8, # [a3] Vec < u8 >) ;"#);
34+
checker!(attr_trait_issue_64682, "fn trait5 (# [a1] # [a2] arg1 : u8, # [a3] arg2 : u8) ;");
35+
checker!(rename_params, r#"impl Foo
36+
{
37+
fn hello
38+
(# [angery (true)] a : i32, # [a2] b : i32, # [what = "how"] c : u32) { }
39+
fn hello2
40+
(# [a1] # [a2] a : i32, # [what = "how"] b : i32, # [angery (true)] c :
41+
u32) { } fn hello_self
42+
(# [a1] # [a2] & self, # [a1] # [a2] a : i32, # [what = "how"] b : i32, #
43+
[angery (true)] c : u32) { }
4444
}"#);

0 commit comments

Comments
 (0)
Please sign in to comment.