From 3ed6caae60794c6fade76486b2fbe2a173eb1943 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 7 Jan 2021 11:43:21 -0500 Subject: [PATCH] Synthesize a `TokenStream` for `StmtKind::Empty` Fixes #80760 --- compiler/rustc_parse/src/lib.rs | 11 +++++++- .../ui/proc-macro/issue-80760-empty-stmt.rs | 26 +++++++++++++++++++ .../proc-macro/issue-80760-empty-stmt.stdout | 14 ++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/proc-macro/issue-80760-empty-stmt.rs create mode 100644 src/test/ui/proc-macro/issue-80760-empty-stmt.stdout diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 4fa9768febb..19504e5f272 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -257,7 +257,16 @@ pub fn nt_to_tokenstream( let tokens = match *nt { Nonterminal::NtItem(ref item) => prepend_attrs(sess, &item.attrs, nt, item.tokens.as_ref()), Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()), - Nonterminal::NtStmt(ref stmt) => prepend_attrs(sess, stmt.attrs(), nt, stmt.tokens()), + Nonterminal::NtStmt(ref stmt) => { + let do_prepend = |tokens| prepend_attrs(sess, stmt.attrs(), nt, tokens); + if let ast::StmtKind::Empty = stmt.kind { + let tokens: TokenStream = + tokenstream::TokenTree::token(token::Semi, stmt.span).into(); + do_prepend(Some(&LazyTokenStream::new(tokens))) + } else { + do_prepend(stmt.tokens()) + } + } Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()), Nonterminal::NtTy(ref ty) => convert_tokens(ty.tokens.as_ref()), Nonterminal::NtIdent(ident, is_raw) => { diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.rs b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs new file mode 100644 index 00000000000..86865af0b52 --- /dev/null +++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs @@ -0,0 +1,26 @@ +// check-pass +// aux-build:test-macros.rs +// compile-flags: -Z span-debug + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate test_macros; + +macro_rules! empty_stmt { + ($s:stmt) => { + print_bang!($s); + + // Currently, all attributes are ignored + // on an empty statement + #[print_attr] + #[rustc_dummy(first)] + #[rustc_dummy(second)] + $s + } +} + +fn main() { + empty_stmt!(;); +} diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout new file mode 100644 index 00000000000..4b7ed874307 --- /dev/null +++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout @@ -0,0 +1,14 @@ +PRINT-BANG INPUT (DISPLAY): ; +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Punct { + ch: ';', + spacing: Alone, + span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0), + }, + ], + span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4), + }, +]