From 6c643a070c1f725159e626697f13b45b72f23069 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 26 Mar 2020 15:54:47 +0100 Subject: [PATCH] suggest semi on expr mac!() good as stmt mac!(). --- src/librustc_expand/mbe/macro_rules.rs | 19 ++++++++++- ...e-34421-mac-expr-bad-stmt-good-add-semi.rs | 15 ++++++++ ...421-mac-expr-bad-stmt-good-add-semi.stderr | 34 +++++++++++++++++++ .../macro-in-expression-context-2.stderr | 6 ++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs create mode 100644 src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index b9477be57ddda..0e70fdbd9c146 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -86,6 +86,7 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa fn emit_frag_parse_err( mut e: DiagnosticBuilder<'_>, parser: &Parser<'_>, + orig_parser: &mut Parser<'_>, site_span: Span, macro_ident: ast::Ident, arm_span: Span, @@ -118,6 +119,21 @@ fn emit_frag_parse_err( AstFragmentKind::Pat if macro_ident.name == sym::vec => { suggest_slice_pat(&mut e, site_span, parser); } + // 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, + ); + } + }, _ => annotate_err_with_kind(&mut e, kind, site_span), }; e.emit(); @@ -126,10 +142,11 @@ fn emit_frag_parse_err( impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; + let snapshot = &mut parser.clone(); let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { - emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind); + emit_frag_parse_err(err, parser, snapshot, site_span, macro_ident, arm_span, kind); return kind.dummy(site_span); } }; diff --git a/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs b/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs new file mode 100644 index 0000000000000..d78139365549a --- /dev/null +++ b/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs @@ -0,0 +1,15 @@ +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() {} diff --git a/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr b/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr new file mode 100644 index 0000000000000..c8d69640071c6 --- /dev/null +++ b/src/test/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr @@ -0,0 +1,34 @@ +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 + diff --git a/src/test/ui/macros/macro-in-expression-context-2.stderr b/src/test/ui/macros/macro-in-expression-context-2.stderr index 672871c49ca5a..8f9660963937f 100644 --- a/src/test/ui/macros/macro-in-expression-context-2.stderr +++ b/src/test/ui/macros/macro-in-expression-context-2.stderr @@ -6,6 +6,12 @@ LL | macro_rules! empty { () => () } ... LL | _ => { empty!() } | ^^^^^^^^ expected expression + | + = 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!(); } + | ^ error: aborting due to previous error