From eb5d8923fce0a025921368d175905c9cab481954 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Apr 2025 14:23:49 +1100 Subject: [PATCH 1/2] Allow for missing invisible close delim when reparsing an expression. This can happen when invalid syntax is passed to a declarative macro. We shouldn't be too strict about the token stream position once the parser has rejected the invalid syntax. Fixes #139248. --- compiler/rustc_parse/src/parser/mod.rs | 7 +++- .../ui/macros/no-close-delim-issue-139248.rs | 14 ++++++++ .../macros/no-close-delim-issue-139248.stderr | 33 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/no-close-delim-issue-139248.rs create mode 100644 tests/ui/macros/no-close-delim-issue-139248.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3b0861a9942a..b277cb804fa7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -793,7 +793,12 @@ impl<'a> Parser<'a> { self.bump(); Some(res) } else { - panic!("no close delim when reparsing {mv_kind:?}"); + // This can occur when invalid syntax is passed to a decl macro. E.g. see #139248, + // where the reparse attempt of an invalid expr consumed the trailing invisible + // delimiter. + self.dcx() + .span_delayed_bug(self.token.span, "no close delim with reparsing {mv_kind:?}"); + None } } else { None diff --git a/tests/ui/macros/no-close-delim-issue-139248.rs b/tests/ui/macros/no-close-delim-issue-139248.rs new file mode 100644 index 000000000000..86583b2724ed --- /dev/null +++ b/tests/ui/macros/no-close-delim-issue-139248.rs @@ -0,0 +1,14 @@ +// This code caused a "no close delim when reparsing Expr" ICE in #139248. + +macro_rules! m { + (static a : () = $e:expr) => { + static a : () = $e; + //~^ ERROR macro expansion ends with an incomplete expression: expected expression + } +} + +m! { static a : () = (if b) } +//~^ ERROR expected `{`, found `)` +//~| ERROR expected `{`, found `)` + +fn main() {} diff --git a/tests/ui/macros/no-close-delim-issue-139248.stderr b/tests/ui/macros/no-close-delim-issue-139248.stderr new file mode 100644 index 000000000000..6ed41ae9b46a --- /dev/null +++ b/tests/ui/macros/no-close-delim-issue-139248.stderr @@ -0,0 +1,33 @@ +error: expected `{`, found `)` + --> $DIR/no-close-delim-issue-139248.rs:10:27 + | +LL | m! { static a : () = (if b) } + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/no-close-delim-issue-139248.rs:10:26 + | +LL | m! { static a : () = (if b) } + | ^ + +error: expected `{`, found `)` + --> $DIR/no-close-delim-issue-139248.rs:10:27 + | +LL | m! { static a : () = (if b) } + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/no-close-delim-issue-139248.rs:10:26 + | +LL | m! { static a : () = (if b) } + | ^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: macro expansion ends with an incomplete expression: expected expression + --> $DIR/no-close-delim-issue-139248.rs:5:28 + | +LL | static a : () = $e; + | ^ expected expression + +error: aborting due to 3 previous errors + From e177921ae9bca5d697e682551c27c5baefcfbb60 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Apr 2025 13:54:24 +1000 Subject: [PATCH 2/2] Allow for reparsing failure when reparsing a pasted metavar. Fixes #139445. The additional errors aren't great but the first one is still good and it's the most important, and imperfect errors are better than ICEing. --- compiler/rustc_parse/src/parser/mod.rs | 13 +++++++--- .../macros/failed-to-reparse-issue-139445.rs | 6 +++++ .../failed-to-reparse-issue-139445.stderr | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/ui/macros/failed-to-reparse-issue-139445.rs create mode 100644 tests/ui/macros/failed-to-reparse-issue-139445.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b277cb804fa7..fafd1b1ae007 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -782,9 +782,16 @@ impl<'a> Parser<'a> { // Recovery is disabled when parsing macro arguments, so it must // also be disabled when reparsing pasted macro arguments, // otherwise we get inconsistent results (e.g. #137874). - let res = self.with_recovery(Recovery::Forbidden, |this| { - f(this).expect("failed to reparse {mv_kind:?}") - }); + let res = self.with_recovery(Recovery::Forbidden, |this| f(this)); + + let res = match res { + Ok(res) => res, + Err(err) => { + // This can occur in unusual error cases, e.g. #139445. + err.delay_as_bug(); + return None; + } + }; if let token::CloseDelim(delim) = self.token.kind && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.rs b/tests/ui/macros/failed-to-reparse-issue-139445.rs new file mode 100644 index 000000000000..babe26b9d293 --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-139445.rs @@ -0,0 +1,6 @@ +fn main() { + assert_eq!(3, 'a,) + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected expression, found `` +} diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.stderr b/tests/ui/macros/failed-to-reparse-issue-139445.stderr new file mode 100644 index 000000000000..6f7d88fb3446 --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-139445.stderr @@ -0,0 +1,24 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/failed-to-reparse-issue-139445.rs:2:21 + | +LL | assert_eq!(3, 'a,) + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/failed-to-reparse-issue-139445.rs:2:5 + | +LL | assert_eq!(3, 'a,) + | ^^^^^^^^^^^^^^^^^^ expected `while`, `for`, `loop` or `{` after a label + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `` + --> $DIR/failed-to-reparse-issue-139445.rs:2:5 + | +LL | assert_eq!(3, 'a,) + | ^^^^^^^^^^^^^^^^^^ expected expression + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors +