Skip to content

Commit

Permalink
expand: Stop using nonterminals when passing items to proc macro attr…
Browse files Browse the repository at this point in the history
…ibutes
  • Loading branch information
petrochenkov committed Feb 29, 2020
1 parent e9bca51 commit 1968fd4
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 81 deletions.
24 changes: 23 additions & 1 deletion src/librustc_expand/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS};
use rustc_parse::{self, nt_to_tokenstream, parser, DirectoryOwnership, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
Expand Down Expand Up @@ -118,6 +118,28 @@ impl Annotatable {
}
}

crate fn into_tokenstream(self, sess: &ParseSess) -> TokenStream {
let span = self.span();
let nt = match self {
Annotatable::Item(item) => token::NtItem(item),
Annotatable::TraitItem(item)
| Annotatable::ImplItem(item)
| Annotatable::ForeignItem(item) => {
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
}
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
Annotatable::Expr(expr) => token::NtExpr(expr),
Annotatable::Arm(..)
| Annotatable::Field(..)
| Annotatable::FieldPat(..)
| Annotatable::GenericParam(..)
| Annotatable::Param(..)
| Annotatable::StructField(..)
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
};
nt_to_tokenstream(&nt, sess, span)
}

pub fn expect_item(self) -> P<ast::Item> {
match self {
Annotatable::Item(i) => i,
Expand Down
30 changes: 3 additions & 27 deletions src/librustc_expand/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::proc_macro::collect_derives;

use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::Features;
use rustc_parse::configure;
Expand All @@ -25,7 +24,7 @@ use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
use syntax::mut_visit::*;
use syntax::ptr::P;
use syntax::token;
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::tokenstream::TokenStream;
use syntax::util::map_in_place::MapInPlace;
use syntax::visit::{self, AssocCtxt, Visitor};

Expand Down Expand Up @@ -668,36 +667,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
SyntaxExtensionKind::Attr(expander) => {
self.gate_proc_macro_input(&item);
self.gate_proc_macro_attr_item(span, &item);
// `Annotatable` can be converted into tokens directly, but we are packing it
// into a nonterminal as a piece of AST to make the produced token stream
// look nicer in pretty-printed form. This may be no longer necessary.
let item_tok = TokenTree::token(
token::Interpolated(Lrc::new(match item {
Annotatable::Item(item) => token::NtItem(item),
Annotatable::TraitItem(item)
| Annotatable::ImplItem(item)
| Annotatable::ForeignItem(item) => {
token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
}
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
Annotatable::Expr(expr) => token::NtExpr(expr),
Annotatable::Arm(..)
| Annotatable::Field(..)
| Annotatable::FieldPat(..)
| Annotatable::GenericParam(..)
| Annotatable::Param(..)
| Annotatable::StructField(..)
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
})),
DUMMY_SP,
)
.into();
let tokens = item.into_tokenstream(self.cx.parse_sess);
let item = attr.unwrap_normal_item();
if let MacArgs::Eq(..) = item.args {
self.cx.span_err(span, "key-value macro attributes are not supported");
}
let tok_result =
expander.expand(self.cx, span, item.args.inner_tokens(), item_tok);
expander.expand(self.cx, span, item.args.inner_tokens(), tokens);
self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span)
}
SyntaxExtensionKind::LegacyAttr(expander) => {
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/async-await/issues/issue-60674.stdout
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
async fn f(mut x: u8) { }
async fn g((mut x, y, mut z): (u8, u8, u8)) { }
async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) { }
async fn f (mut x : u8) { }
async fn g ((mut x, y, mut z) : (u8, u8, u8)) { }
async fn g (mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) { }
2 changes: 1 addition & 1 deletion src/test/ui/proc-macro/auxiliary/attr-args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {

let input = input.to_string();

assert_eq!(input, "fn foo() { }");
assert_eq!(input, "fn foo () { }");

r#"
fn foo() -> &'static str { "Hello, world!" }
Expand Down
10 changes: 4 additions & 6 deletions src/test/ui/proc-macro/auxiliary/attr-cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ use proc_macro::TokenStream;
pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream {
let input_str = input.to_string();

assert_eq!(input_str, "fn outer() -> u8 {
#[cfg(foo)]
fn inner() -> u8 { 1 }
#[cfg(bar)]
fn inner() -> u8 { 2 }
inner()
assert_eq!(input_str, "fn outer () -> u8
{
# [cfg (foo)] fn inner () -> u8 { 1 } # [cfg (bar)] fn inner () -> u8
{ 2 } inner ()
}");

input
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/proc-macro/auxiliary/attr-on-trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream {
drop(attr);
assert_eq!(item.to_string(), "fn foo() { }");
assert_eq!(item.to_string(), "fn foo () { }");
"fn foo(&self);".parse().unwrap()
}
8 changes: 4 additions & 4 deletions src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
item
}

#[proc_macro_attribute]
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\", string);");
assert_eq!(item.to_string(), "println ! (\"{}\", string) ;");
item
}

#[proc_macro_attribute]
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "print_str(\"string\")");
assert_eq!(item.to_string(), "print_str (\"string\")");
item
}

#[proc_macro_attribute]
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\", string)");
assert_eq!(item.to_string(), "println ! (\"{}\", string)");
item
}

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
item
}

#[proc_macro_attribute]
pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\", string);");
assert_eq!(item.to_string(), "println ! (\"{}\", string) ;");
item
}

#[proc_macro_attribute]
pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "print_str(\"string\")");
assert_eq!(item.to_string(), "print_str (\"string\")");
item
}

#[proc_macro_attribute]
pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
assert!(attr.to_string().is_empty());
assert_eq!(item.to_string(), "println!(\"{}\", string)");
assert_eq!(item.to_string(), "println ! (\"{}\", string)");
item
}

Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
span: #3 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ;
PRINT-ATTR INPUT (DISPLAY): struct A (identity ! ($crate :: S)) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
Expand Down Expand Up @@ -54,8 +53,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
span: #3 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ;
PRINT-ATTR INPUT (DISPLAY): struct B (identity ! ($crate :: S)) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/proc-macro/dollar-crate.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
span: #3 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
Expand Down Expand Up @@ -160,8 +159,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
span: #13 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
Expand Down
48 changes: 24 additions & 24 deletions src/test/ui/rfc-2565-param-attrs/auxiliary/param-attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,28 @@ macro_rules! checker {
}
}

checker!(attr_extern, r#"extern "C" {
fn ffi(#[a1] arg1: i32, #[a2] ...);
}"#);
checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) { }"#);
checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);");
checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }");
checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) { }");
checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) { }");
checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) { }");
checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) { }");
checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) { }");
checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);");
checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);");
checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);");
checker!(attr_trait_4, "fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);");
checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);");
checker!(rename_params, r#"impl Foo {
fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) { }
fn hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32,
#[angery(true)] c: u32) {
}
fn hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32,
#[what = "how"] b: i32, #[angery(true)] c: u32) {
}
checker!(attr_extern, r#"extern "C" { fn ffi (# [a1] arg1 : i32, # [a2] ...) ; }"#);
checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar (arg1 : i32, # [a1] mut args : ...) { }"#);
checker!(attr_alias, "type Alias = fn (# [a1] u8, # [a2] ...) ;");
checker!(attr_free, "fn free (# [a1] arg1 : u8) { let lam = | # [a2] W (x), # [a3] y | () ; }");
checker!(attr_inherent_1, "fn inherent1 (# [a1] self, # [a2] arg1 : u8) { }");
checker!(attr_inherent_2, "fn inherent2 (# [a1] & self, # [a2] arg1 : u8) { }");
checker!(attr_inherent_3, "fn inherent3 < 'a > (# [a1] & 'a mut self, # [a2] arg1 : u8) { }");
checker!(attr_inherent_4, "fn inherent4 < 'a > (# [a1] self : Box < Self >, # [a2] arg1 : u8) { }");
checker!(attr_inherent_issue_64682, "fn inherent5 (# [a1] # [a2] arg1 : u8, # [a3] arg2 : u8) { }");
checker!(attr_trait_1, "fn trait1 (# [a1] self, # [a2] arg1 : u8) ;");
checker!(attr_trait_2, "fn trait2 (# [a1] & self, # [a2] arg1 : u8) ;");
checker!(attr_trait_3, "fn trait3 < 'a > (# [a1] & 'a mut self, # [a2] arg1 : u8) ;");
checker!(attr_trait_4, r#"fn trait4 < 'a >
(# [a1] self : Box < Self >, # [a2] arg1 : u8, # [a3] Vec < u8 >) ;"#);
checker!(attr_trait_issue_64682, "fn trait5 (# [a1] # [a2] arg1 : u8, # [a3] arg2 : u8) ;");
checker!(rename_params, r#"impl Foo
{
fn hello
(# [angery (true)] a : i32, # [a2] b : i32, # [what = "how"] c : u32) { }
fn hello2
(# [a1] # [a2] a : i32, # [what = "how"] b : i32, # [angery (true)] c :
u32) { } fn hello_self
(# [a1] # [a2] & self, # [a1] # [a2] a : i32, # [what = "how"] b : i32, #
[angery (true)] c : u32) { }
}"#);

0 comments on commit 1968fd4

Please sign in to comment.