Skip to content

Commit 6c2700b

Browse files
authored
Rollup merge of #150988 - chenyukang:yukang-fix-150899-macro-rules, r=petrochenkov
Improve code suggestion for incorrect macro_rules! usage Fixes #150899
2 parents 5df4f59 + caf7cdf commit 6c2700b

File tree

6 files changed

+89
-27
lines changed

6 files changed

+89
-27
lines changed

compiler/rustc_parse/src/parser/item.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ impl<'a> Parser<'a> {
534534
match self.parse_delim_args() {
535535
// `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
536536
Ok(args) => {
537-
self.eat_semi_for_macro_if_needed(&args);
537+
self.eat_semi_for_macro_if_needed(&args, Some(&path));
538538
self.complain_if_pub_macro(vis, false);
539539
Ok(MacCall { path, args })
540540
}
@@ -2392,7 +2392,7 @@ impl<'a> Parser<'a> {
23922392
}
23932393

23942394
let body = self.parse_delim_args()?;
2395-
self.eat_semi_for_macro_if_needed(&body);
2395+
self.eat_semi_for_macro_if_needed(&body, None);
23962396
self.complain_if_pub_macro(vis, true);
23972397

23982398
Ok(ItemKind::MacroDef(
@@ -2417,13 +2417,13 @@ impl<'a> Parser<'a> {
24172417
}
24182418
}
24192419

2420-
fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs) {
2420+
fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
24212421
if args.need_semicolon() && !self.eat(exp!(Semi)) {
2422-
self.report_invalid_macro_expansion_item(args);
2422+
self.report_invalid_macro_expansion_item(args, path);
24232423
}
24242424
}
24252425

2426-
fn report_invalid_macro_expansion_item(&self, args: &DelimArgs) {
2426+
fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
24272427
let span = args.dspan.entire();
24282428
let mut err = self.dcx().struct_span_err(
24292429
span,
@@ -2433,17 +2433,32 @@ impl<'a> Parser<'a> {
24332433
// macros within the same crate (that we can fix), which is sad.
24342434
if !span.from_expansion() {
24352435
let DelimSpan { open, close } = args.dspan;
2436-
err.multipart_suggestion(
2437-
"change the delimiters to curly braces",
2438-
vec![(open, "{".to_string()), (close, '}'.to_string())],
2439-
Applicability::MaybeIncorrect,
2440-
);
2441-
err.span_suggestion(
2442-
span.with_neighbor(self.token.span).shrink_to_hi(),
2443-
"add a semicolon",
2444-
';',
2445-
Applicability::MaybeIncorrect,
2446-
);
2436+
// Check if this looks like `macro_rules!(name) { ... }`
2437+
// a common mistake when trying to define a macro.
2438+
if let Some(path) = path
2439+
&& path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
2440+
&& args.delim == Delimiter::Parenthesis
2441+
{
2442+
let replace =
2443+
if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
2444+
err.multipart_suggestion(
2445+
"to define a macro, remove the parentheses around the macro name",
2446+
vec![(open, replace.to_string()), (close, String::new())],
2447+
Applicability::MachineApplicable,
2448+
);
2449+
} else {
2450+
err.multipart_suggestion(
2451+
"change the delimiters to curly braces",
2452+
vec![(open, "{".to_string()), (close, '}'.to_string())],
2453+
Applicability::MaybeIncorrect,
2454+
);
2455+
err.span_suggestion(
2456+
span.with_neighbor(self.token.span).shrink_to_hi(),
2457+
"add a semicolon",
2458+
';',
2459+
Applicability::MaybeIncorrect,
2460+
);
2461+
}
24472462
}
24482463
err.emit();
24492464
}

tests/ui/macros/issue-118786.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![allow(unused_macros)]
2+
//@ compile-flags: --crate-type lib
3+
//@ dont-require-annotations: NOTE
4+
//@ run-rustfix
5+
6+
// Regression test for issue 118786
7+
8+
macro_rules! make_macro {
9+
($macro_name:tt) => {
10+
macro_rules! $macro_name {
11+
//~^ ERROR macro expansion ignores `{` and any tokens following
12+
//~| ERROR cannot find macro `macro_rules` in this scope
13+
//~| NOTE put a macro name here
14+
() => {}
15+
}
16+
}
17+
}
18+
19+
make_macro!(meow);
20+
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon

tests/ui/macros/issue-118786.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
//@ compile-flags: --crate-type lib -O -C debug-assertions=yes
1+
#![allow(unused_macros)]
2+
//@ compile-flags: --crate-type lib
23
//@ dont-require-annotations: NOTE
4+
//@ run-rustfix
35

46
// Regression test for issue 118786
57

tests/ui/macros/issue-118786.stderr

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
error: macros that expand to items must be delimited with braces or followed by a semicolon
2-
--> $DIR/issue-118786.rs:17:13
2+
--> $DIR/issue-118786.rs:19:13
33
|
44
LL | make_macro!((meow));
55
| ^^^^^^
66
|
7-
help: change the delimiters to curly braces
7+
help: to define a macro, remove the parentheses around the macro name
88
|
99
LL - make_macro!((meow));
10-
LL + make_macro!({meow});
10+
LL + make_macro!(meow);
1111
|
12-
help: add a semicolon
13-
|
14-
LL | macro_rules! $macro_name; {
15-
| +
1612

1713
error: macro expansion ignores `{` and any tokens following
18-
--> $DIR/issue-118786.rs:8:34
14+
--> $DIR/issue-118786.rs:10:34
1915
|
2016
LL | macro_rules! $macro_name {
2117
| ^
@@ -26,7 +22,7 @@ LL | make_macro!((meow));
2622
= note: the usage of `make_macro!` is likely invalid in item context
2723

2824
error: cannot find macro `macro_rules` in this scope
29-
--> $DIR/issue-118786.rs:8:9
25+
--> $DIR/issue-118786.rs:10:9
3026
|
3127
LL | macro_rules! $macro_name {
3228
| ^^^^^^^^^^^
@@ -35,7 +31,7 @@ LL | make_macro!((meow));
3531
| ------------------- in this macro invocation
3632
|
3733
note: maybe you have forgotten to define a name for this `macro_rules!`
38-
--> $DIR/issue-118786.rs:8:20
34+
--> $DIR/issue-118786.rs:10:20
3935
|
4036
LL | macro_rules! $macro_name {
4137
| ^ put a macro name here
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
macro_rules!(i_think_the_name_should_go_here) {
2+
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
3+
//~| ERROR expected item, found `{`
4+
() => {}
5+
}
6+
7+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: macros that expand to items must be delimited with braces or followed by a semicolon
2+
--> $DIR/macro-rules-paren-name-issue-150899.rs:1:13
3+
|
4+
LL | macro_rules!(i_think_the_name_should_go_here) {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: to define a macro, remove the parentheses around the macro name
8+
|
9+
LL - macro_rules!(i_think_the_name_should_go_here) {
10+
LL + macro_rules! i_think_the_name_should_go_here {
11+
|
12+
13+
error: expected item, found `{`
14+
--> $DIR/macro-rules-paren-name-issue-150899.rs:1:47
15+
|
16+
LL | macro_rules!(i_think_the_name_should_go_here) {
17+
| ^ expected item
18+
|
19+
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>
20+
21+
error: aborting due to 2 previous errors
22+

0 commit comments

Comments
 (0)