From 9c9f40656dadf3c2a05b2d5add875f5d0d3541d8 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 24 Nov 2020 14:47:49 -0500 Subject: [PATCH] Invoke attributes on the statement for statement items --- compiler/rustc_expand/src/base.rs | 9 + compiler/rustc_expand/src/expand.rs | 25 ++- compiler/rustc_expand/src/proc_macro.rs | 21 +- .../ui/proc-macro/allowed-attr-stmt-expr.rs | 59 ++++++ .../proc-macro/allowed-attr-stmt-expr.stdout | 187 ++++++++++++++++++ src/test/ui/proc-macro/attr-stmt-expr.rs | 32 +++ src/test/ui/proc-macro/attr-stmt-expr.stderr | 4 +- src/test/ui/proc-macro/attr-stmt-expr.stdout | 187 ++++++++++++++++++ src/test/ui/proc-macro/keep-expr-tokens.rs | 9 + .../ui/proc-macro/keep-expr-tokens.stderr | 4 +- .../ui/proc-macro/keep-expr-tokens.stdout | 46 +++++ 11 files changed, 574 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/proc-macro/allowed-attr-stmt-expr.rs create mode 100644 src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout create mode 100644 src/test/ui/proc-macro/attr-stmt-expr.stdout create mode 100644 src/test/ui/proc-macro/keep-expr-tokens.stdout diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 1c76c31e1a7..1b5c06a96bc 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -234,6 +234,15 @@ impl Annotatable { pub fn derive_allowed(&self) -> bool { match *self { + Annotatable::Stmt(ref stmt) => match stmt.kind { + ast::StmtKind::Item(ref item) => match item.kind { + ast::ItemKind::Struct(..) + | ast::ItemKind::Enum(..) + | ast::ItemKind::Union(..) => true, + _ => false, + }, + _ => false, + }, Annotatable::Item(ref item) => match item.kind { ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => { true diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5be2fee8b38..ce560c6c178 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -795,7 +795,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { | Annotatable::TraitItem(_) | Annotatable::ImplItem(_) | Annotatable::ForeignItem(_) => return, - Annotatable::Stmt(_) => "statements", + Annotatable::Stmt(stmt) => { + // Attributes are stable on item statements, + // but unstable on all other kinds of statements + if stmt.is_item() { + return; + } + "statements" + } Annotatable::Expr(_) => "expressions", Annotatable::Arm(..) | Annotatable::Field(..) @@ -1266,9 +1273,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { - // FIXME: Handle custom attributes on statements (#15701). - let attr = - if stmt.is_item() { None } else { self.take_first_attr_no_derive(&mut stmt) }; + let attr = if stmt.is_item() { + // FIXME: Implement proper token collection for statements + if let StmtKind::Item(item) = &mut stmt.kind { + stmt.tokens = item.tokens.take() + } else { + unreachable!() + }; + self.take_first_attr(&mut stmt) + } else { + // Ignore derives on non-item statements for backwards compatibility. + // This will result in a unused attribute warning + self.take_first_attr_no_derive(&mut stmt) + }; if let Some(attr) = attr { return self diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index dea167740ed..36707a1ae27 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -1,6 +1,7 @@ use crate::base::{self, *}; use crate::proc_macro_server; +use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::{self as ast, *}; @@ -74,8 +75,20 @@ impl MultiItemModifier for ProcMacroDerive { _meta_item: &ast::MetaItem, item: Annotatable, ) -> ExpandResult, Annotatable> { + // We need special handling for statement items + // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) + let mut is_stmt = false; let item = match item { Annotatable::Item(item) => token::NtItem(item), + Annotatable::Stmt(stmt) => { + is_stmt = true; + assert!(stmt.is_item()); + + // A proc macro can't observe the fact that we're passing + // them an `NtStmt` - it can only see the underlying tokens + // of the wrapped item + token::NtStmt(stmt.into_inner()) + } _ => unreachable!(), }; let input = if item.pretty_printing_compatibility_hack() { @@ -106,7 +119,13 @@ impl MultiItemModifier for ProcMacroDerive { loop { match parser.parse_item() { Ok(None) => break, - Ok(Some(item)) => items.push(Annotatable::Item(item)), + Ok(Some(item)) => { + if is_stmt { + items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item)))); + } else { + items.push(Annotatable::Item(item)); + } + } Err(mut err) => { err.emit(); break; diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs new file mode 100644 index 00000000000..03c10a43248 --- /dev/null +++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs @@ -0,0 +1,59 @@ +// aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug +// check-pass + +#![feature(proc_macro_hygiene)] +#![feature(stmt_expr_attributes)] +#![feature(rustc_attrs)] +#![allow(dead_code)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +extern crate attr_stmt_expr; +extern crate test_macros; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr}; +use test_macros::print_attr; +use std::println; + +fn print_str(string: &'static str) { + // macros are handled a bit differently + #[expect_print_expr] + println!("{}", string) +} + +macro_rules! make_stmt { + ($stmt:stmt) => { + $stmt + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + + +fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] + #[expect_let] + let string = "Hello, world!"; + + #[print_attr] + #[expect_print_stmt] + println!("{}", string); + + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {}; + + #[expect_expr] + print_str("string") +} diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout new file mode 100644 index 00000000000..0c7ac4fb682 --- /dev/null +++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout @@ -0,0 +1,187 @@ +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "let", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_print_stmt] println ! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_print_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "println", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "string", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt ! (#[allow(dead_code)] struct Bar { }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "struct", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "Other", + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/allowed-attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] diff --git a/src/test/ui/proc-macro/attr-stmt-expr.rs b/src/test/ui/proc-macro/attr-stmt-expr.rs index 14a392db4e1..ca1b163c986 100644 --- a/src/test/ui/proc-macro/attr-stmt-expr.rs +++ b/src/test/ui/proc-macro/attr-stmt-expr.rs @@ -1,8 +1,17 @@ // aux-build:attr-stmt-expr.rs +// aux-build:test-macros.rs +// compile-flags: -Z span-debug #![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; +extern crate test_macros; extern crate attr_stmt_expr; + +use test_macros::print_attr; +use std::println; use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr}; fn print_str(string: &'static str) { @@ -13,13 +22,36 @@ fn print_str(string: &'static str) { println!("{}", string) } +macro_rules! make_stmt { + ($stmt:stmt) => { + $stmt + } +} + +macro_rules! second_make_stmt { + ($stmt:stmt) => { + make_stmt!($stmt); + } +} + fn main() { + make_stmt!(struct Foo {}); + + #[print_attr] #[expect_let] let string = "Hello, world!"; + #[print_attr] #[expect_print_stmt] println!("{}", string); + #[print_attr] + second_make_stmt!(#[allow(dead_code)] struct Bar {}); + + #[print_attr] + #[rustc_dummy] + struct Other {} + #[expect_expr] //~^ ERROR attributes on expressions are experimental //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr index 0d6f247cf83..7bd60e8ee77 100644 --- a/src/test/ui/proc-macro/attr-stmt-expr.stderr +++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/attr-stmt-expr.rs:10:5 + --> $DIR/attr-stmt-expr.rs:19:5 | LL | #[expect_print_expr] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #[expect_print_expr] = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable error[E0658]: attributes on expressions are experimental - --> $DIR/attr-stmt-expr.rs:23:5 + --> $DIR/attr-stmt-expr.rs:55:5 | LL | #[expect_expr] | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stdout b/src/test/ui/proc-macro/attr-stmt-expr.stdout new file mode 100644 index 00000000000..5c1b586725b --- /dev/null +++ b/src/test/ui/proc-macro/attr-stmt-expr.stdout @@ -0,0 +1,187 @@ +PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_let", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "let", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '=', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Literal { + kind: Str, + symbol: "Hello, world!", + suffix: None, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[expect_print_stmt] println ! ("{}", string) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "expect_print_stmt", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "println", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Literal { + kind: Str, + symbol: "{}", + suffix: None, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "string", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): second_make_stmt ! (#[allow(dead_code)] struct Bar { }) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "second_make_stmt", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "allow", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "dead_code", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "Bar", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other { } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + ], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "struct", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Ident { + ident: "Other", + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [], + span: $DIR/attr-stmt-expr.rs:1:1: 1:1 (#0), + }, +] diff --git a/src/test/ui/proc-macro/keep-expr-tokens.rs b/src/test/ui/proc-macro/keep-expr-tokens.rs index 888785363cf..0bf889a855d 100644 --- a/src/test/ui/proc-macro/keep-expr-tokens.rs +++ b/src/test/ui/proc-macro/keep-expr-tokens.rs @@ -1,7 +1,12 @@ // aux-build:test-macros.rs +// compile-flags: -Z span-debug #![feature(stmt_expr_attributes)] #![feature(proc_macro_hygiene)] +#![feature(rustc_attrs)] + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; extern crate test_macros; @@ -12,4 +17,8 @@ fn main() { for item in missing_fn() {} //~ ERROR cannot find (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); //~ ERROR cannot + + #[test_macros::print_attr] + #[rustc_dummy] + { 1 +1; } // Don't change the weird spacing of the '+' } diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stderr b/src/test/ui/proc-macro/keep-expr-tokens.stderr index 2be8c0184da..11052d11c25 100644 --- a/src/test/ui/proc-macro/keep-expr-tokens.stderr +++ b/src/test/ui/proc-macro/keep-expr-tokens.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find function `missing_fn` in this scope - --> $DIR/keep-expr-tokens.rs:12:17 + --> $DIR/keep-expr-tokens.rs:17:17 | LL | for item in missing_fn() {} | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find value `bad` in this scope - --> $DIR/keep-expr-tokens.rs:14:62 + --> $DIR/keep-expr-tokens.rs:19:62 | LL | (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); | ^^^ not found in this scope diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stdout b/src/test/ui/proc-macro/keep-expr-tokens.stdout new file mode 100644 index 00000000000..fcd72a0e017 --- /dev/null +++ b/src/test/ui/proc-macro/keep-expr-tokens.stdout @@ -0,0 +1,46 @@ +PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:22:5: 22:6 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustc_dummy", + span: $DIR/keep-expr-tokens.rs:22:7: 22:18 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:22:6: 22:19 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:7: 23:8 (#0), + }, + Punct { + ch: '+', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:9: 23:10 (#0), + }, + Literal { + kind: Integer, + symbol: "1", + suffix: None, + span: $DIR/keep-expr-tokens.rs:23:10: 23:11 (#0), + }, + Punct { + ch: ';', + spacing: Alone, + span: $DIR/keep-expr-tokens.rs:23:11: 23:12 (#0), + }, + ], + span: $DIR/keep-expr-tokens.rs:23:5: 23:14 (#0), + }, +]