Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ impl<'a> Parser<'a> {
match self.parse_delim_args() {
// `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
Ok(args) => {
self.eat_semi_for_macro_if_needed(&args);
self.eat_semi_for_macro_if_needed(&args, Some(&path));
self.complain_if_pub_macro(vis, false);
Ok(MacCall { path, args })
}
Expand Down Expand Up @@ -2392,7 +2392,7 @@ impl<'a> Parser<'a> {
}

let body = self.parse_delim_args()?;
self.eat_semi_for_macro_if_needed(&body);
self.eat_semi_for_macro_if_needed(&body, None);
self.complain_if_pub_macro(vis, true);

Ok(ItemKind::MacroDef(
Expand All @@ -2417,13 +2417,13 @@ impl<'a> Parser<'a> {
}
}

fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs) {
fn eat_semi_for_macro_if_needed(&mut self, args: &DelimArgs, path: Option<&Path>) {
if args.need_semicolon() && !self.eat(exp!(Semi)) {
self.report_invalid_macro_expansion_item(args);
self.report_invalid_macro_expansion_item(args, path);
}
}

fn report_invalid_macro_expansion_item(&self, args: &DelimArgs) {
fn report_invalid_macro_expansion_item(&self, args: &DelimArgs, path: Option<&Path>) {
let span = args.dspan.entire();
let mut err = self.dcx().struct_span_err(
span,
Expand All @@ -2433,17 +2433,32 @@ impl<'a> Parser<'a> {
// macros within the same crate (that we can fix), which is sad.
if !span.from_expansion() {
let DelimSpan { open, close } = args.dspan;
err.multipart_suggestion(
"change the delimiters to curly braces",
vec![(open, "{".to_string()), (close, '}'.to_string())],
Applicability::MaybeIncorrect,
);
err.span_suggestion(
span.with_neighbor(self.token.span).shrink_to_hi(),
"add a semicolon",
';',
Applicability::MaybeIncorrect,
);
// Check if this looks like `macro_rules!(name) { ... }`
// a common mistake when trying to define a macro.
if let Some(path) = path
&& path.segments.first().is_some_and(|seg| seg.ident.name == sym::macro_rules)
&& args.delim == Delimiter::Parenthesis
{
let replace =
if path.span.hi() + rustc_span::BytePos(1) < open.lo() { "" } else { " " };
err.multipart_suggestion(
"to define a macro, remove the parentheses around the macro name",
vec![(open, replace.to_string()), (close, String::new())],
Applicability::MachineApplicable,
);
} else {
err.multipart_suggestion(
"change the delimiters to curly braces",
vec![(open, "{".to_string()), (close, '}'.to_string())],
Applicability::MaybeIncorrect,
);
err.span_suggestion(
span.with_neighbor(self.token.span).shrink_to_hi(),
"add a semicolon",
';',
Applicability::MaybeIncorrect,
);
}
}
err.emit();
}
Expand Down
20 changes: 20 additions & 0 deletions tests/ui/macros/issue-118786.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![allow(unused_macros)]
//@ compile-flags: --crate-type lib
//@ dont-require-annotations: NOTE
//@ run-rustfix

// Regression test for issue 118786

macro_rules! make_macro {
($macro_name:tt) => {
macro_rules! $macro_name {
//~^ ERROR macro expansion ignores `{` and any tokens following
//~| ERROR cannot find macro `macro_rules` in this scope
//~| NOTE put a macro name here
() => {}
}
}
}

make_macro!(meow);
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
4 changes: 3 additions & 1 deletion tests/ui/macros/issue-118786.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//@ compile-flags: --crate-type lib -O -C debug-assertions=yes
#![allow(unused_macros)]
//@ compile-flags: --crate-type lib
//@ dont-require-annotations: NOTE
//@ run-rustfix

// Regression test for issue 118786

Expand Down
16 changes: 6 additions & 10 deletions tests/ui/macros/issue-118786.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
error: macros that expand to items must be delimited with braces or followed by a semicolon
--> $DIR/issue-118786.rs:17:13
--> $DIR/issue-118786.rs:19:13
|
LL | make_macro!((meow));
| ^^^^^^
|
help: change the delimiters to curly braces
help: to define a macro, remove the parentheses around the macro name
|
LL - make_macro!((meow));
LL + make_macro!({meow});
LL + make_macro!(meow);
|
help: add a semicolon
|
LL | macro_rules! $macro_name; {
| +

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

error: cannot find macro `macro_rules` in this scope
--> $DIR/issue-118786.rs:8:9
--> $DIR/issue-118786.rs:10:9
|
LL | macro_rules! $macro_name {
| ^^^^^^^^^^^
Expand All @@ -35,7 +31,7 @@ LL | make_macro!((meow));
| ------------------- in this macro invocation
|
note: maybe you have forgotten to define a name for this `macro_rules!`
--> $DIR/issue-118786.rs:8:20
--> $DIR/issue-118786.rs:10:20
|
LL | macro_rules! $macro_name {
| ^ put a macro name here
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/parser/macro-rules-paren-name-issue-150899.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
macro_rules!(i_think_the_name_should_go_here) {
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
//~| ERROR expected item, found `{`
() => {}
}

fn main() {}
22 changes: 22 additions & 0 deletions tests/ui/parser/macro-rules-paren-name-issue-150899.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error: macros that expand to items must be delimited with braces or followed by a semicolon
--> $DIR/macro-rules-paren-name-issue-150899.rs:1:13
|
LL | macro_rules!(i_think_the_name_should_go_here) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to define a macro, remove the parentheses around the macro name
|
LL - macro_rules!(i_think_the_name_should_go_here) {
LL + macro_rules! i_think_the_name_should_go_here {
|

error: expected item, found `{`
--> $DIR/macro-rules-paren-name-issue-150899.rs:1:47
|
LL | macro_rules!(i_think_the_name_should_go_here) {
| ^ expected item
|
= note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>

error: aborting due to 2 previous errors

Loading