Change:
This is a regression from stable to beta and nightly. This code is wrong (missing semicolons): Stable prints: Beta and nightly both print: Notice that not only is all the useful information gone, but the compiler aborts after the first error instead of finding the rest. It does not matter whether is on or off. cc
cc me
So this fell through the cracks, and was a stable to nightly/beta regression. It still is a regression, in a way, but only of diagnostics. Could you take a look?
Nominating for prioritization.
So this part of the (previous) stable message: feels like a bug to me anyhow. This part: is sort of good. It'd be nice to preserve a backtrace, at least. And ideally we'd suggest adding a .
Given how much time has past, we're going to call this P-medium for now. However, will try to write up some mentoring instructions (or maybe fix it). He has a plan. =) triage: P-medium
I think the best path forward here is to try parsing an expression macro expansion as a statement before emitting an error. If the macro expansion parses as a statement successfully, we can emit a more helpful error suggesting that the user add a semicolon to the macro invocation.
I'm interested in this but I need informations to understand what to do :)
Current output:
Diagnostics meeting triage: lowering priority as the current error is pretty good, even if not ideal yet.
Current output: (Notice that we recover -- it's not a fatal error now.)

Discussion:
fn emit_frag_parse_err( mut e: DiagnosticBuilder<'_>, parser: &Parser<'_>, <ins> orig_parser: &mut Parser<'_>, </ins> site_span: Span, macro_ident: ast::Ident, arm_span: Span,

AstFragmentKind::Pat if macro_ident.name == sym::vec => { suggest_slice_pat(&mut e, site_span, parser); } <ins> // Try a statement if an expression is wanted but failed and suggest adding `;` to call. AstFragmentKind::Expr => match parse_ast_fragment(orig_parser, AstFragmentKind::Stmts) { Err(mut err) => err.cancel(), Ok(_) => { e.note( "the macro call doesn't expand to an expression, but it can expand to a statement", ); e.span_suggestion_verbose( site_span.shrink_to_hi(), "add `;` to interpret the expansion as a statement", ";".to_string(), Applicability::MaybeIncorrect, ); } }, </ins> _ => annotate_err_with_kind(&mut e, kind, site_span), }; e.emit();

impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; <ins> let snapshot = &mut parser.clone(); </ins> let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { <del> emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind); </del> <ins> emit_frag_parse_err(err, parser, snapshot, site_span, macro_ident, arm_span, kind); </ins> return kind.dummy(site_span); } };

<ins> macro_rules! make_item { ($a:ident) => { struct $a; }; //~^ ERROR expected expression //~| ERROR expected expression } fn a() { make_item!(A) } fn b() { make_item!(B) } fn main() {} </ins>

<ins> error: expected expression, found keyword `struct` --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 | LL |         struct $a; |         ^^^^^^ expected expression ... LL |     make_item!(A) |     ------------- in this macro invocation | = note: the macro call doesn't expand to an expression, but it can expand to a statement = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: add `;` to interpret the expansion as a statement | LL |     make_item!(A); |                  ^ error: expected expression, found keyword `struct` --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 | LL |         struct $a; |         ^^^^^^ expected expression ... LL |     make_item!(B) |     ------------- in this macro invocation | = note: the macro call doesn't expand to an expression, but it can expand to a statement = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: add `;` to interpret the expansion as a statement | LL |     make_item!(B); |                  ^ error: aborting due to 2 previous errors </ins>

... LL |         _ => { empty!() } |                ^^^^^^^^ expected expression <ins> | = note: the macro call doesn't expand to an expression, but it can expand to a statement help: add `;` to interpret the expansion as a statement | LL |         _ => { empty!(); } |                        ^ </ins> error: aborting due to previous error