diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 77f87d5b007e3..a2d507328b389 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -337,19 +337,6 @@ impl DiagnosticMessage { } } } - - /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that - /// this diagnostic message is of the legacy, non-translatable variety. Panics if this - /// assumption does not hold. - /// - /// Don't use this - it exists to support some places that do comparison with diagnostic - /// strings. - pub fn expect_str(&self) -> &str { - match self { - DiagnosticMessage::Str(s) => s, - _ => panic!("expected non-translatable diagnostic message"), - } - } } /// `From` impl that enables existing diagnostic calls to functions which now take diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6d2c7aac6af49..30aa4f0fa3482 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; use rustc_feature::Features; use rustc_lint_defs::builtin::{ RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, @@ -68,19 +68,22 @@ fn emit_frag_parse_err( kind: AstFragmentKind, ) { // FIXME(davidtwco): avoid depending on the error message text - if parser.token == token::Eof && e.message[0].0.expect_str().ends_with(", found ``") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } + if parser.token == token::Eof + && let DiagnosticMessage::Str(message) = &e.message[0].0 + && message.ends_with(", found ``") + { let msg = &e.message[0]; e.message[0] = ( - rustc_errors::DiagnosticMessage::Str(format!( + DiagnosticMessage::Str(format!( "macro expansion ends with an incomplete expression: {}", - msg.0.expect_str().replace(", found ``", ""), + message.replace(", found ``", ""), )), msg.1, ); + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); + } } if e.span.is_dummy() { // Get around lack of span in error (#30128) diff --git a/src/test/ui/macros/issue-102878.rs b/src/test/ui/macros/issue-102878.rs new file mode 100644 index 0000000000000..aac5891939e0c --- /dev/null +++ b/src/test/ui/macros/issue-102878.rs @@ -0,0 +1,10 @@ +macro_rules!test{($l:expr,$_:r)=>({const:y y)} +//~^ ERROR mismatched closing delimiter: `)` +//~| ERROR invalid fragment specifier `r` +//~| ERROR expected identifier, found keyword `const` +//~| ERROR expected identifier, found keyword `const` +//~| ERROR expected identifier, found `:` + +fn s(){test!(1,i)} + +fn main() {} diff --git a/src/test/ui/macros/issue-102878.stderr b/src/test/ui/macros/issue-102878.stderr new file mode 100644 index 0000000000000..e0b8855a38d05 --- /dev/null +++ b/src/test/ui/macros/issue-102878.stderr @@ -0,0 +1,60 @@ +error: mismatched closing delimiter: `)` + --> $DIR/issue-102878.rs:1:35 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | -^ ^ mismatched closing delimiter + | || + | |unclosed delimiter + | closing delimiter possibly meant for this + +error: invalid fragment specifier `r` + --> $DIR/issue-102878.rs:1:27 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: expected identifier, found keyword `const` + --> $DIR/issue-102878.rs:1:36 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^^ expected identifier, found keyword +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `const` to use it as an identifier + | +LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)} + | ++ + +error: expected identifier, found keyword `const` + --> $DIR/issue-102878.rs:1:36 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^^^^^ expected identifier, found keyword +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) +help: escape `const` to use it as an identifier + | +LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)} + | ++ + +error: expected identifier, found `:` + --> $DIR/issue-102878.rs:1:41 + | +LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)} + | ^ expected identifier +... +LL | fn s(){test!(1,i)} + | ---------- in this macro invocation + | + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors +