diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 3e3b4814300..5a3303327db 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -61,6 +61,11 @@ expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses expand_invalid_cfg_no_predicate = `cfg` predicate is not specified expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal + +expand_invalid_fragment_specifier = + invalid fragment specifier `{$fragment}` + .help = {$help} + expand_macro_body_stability = macros cannot have body stability attributes .label = invalid body stability attribute diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2584ff62e98..929f3479466 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -408,3 +408,13 @@ pub struct DuplicateMatcherBinding { #[label(expand_label2)] pub prev: Span, } + +#[derive(Diagnostic)] +#[diag(expand_invalid_fragment_specifier)] +#[help] +pub struct InvalidFragmentSpecifier { + #[primary_span] + pub span: Span, + pub fragment: Ident, + pub help: String, +} diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 4824b67d277..0fdfa563138 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -1,3 +1,4 @@ +use crate::errors; use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; @@ -60,11 +61,11 @@ pub(super) fn parse( Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => { match trees.next() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { - Some((frag, _)) => { + Some((fragment, _)) => { let span = token.span.with_lo(start_sp.lo()); let kind = - token::NonterminalKind::from_symbol(frag.name, || { + token::NonterminalKind::from_symbol(fragment.name, || { // FIXME(#85708) - once we properly decode a foreign // crate's `SyntaxContext::root`, then we can replace // this with just `span.edition()`. A @@ -81,14 +82,13 @@ pub(super) fn parse( }) .unwrap_or_else( || { - let msg = format!( - "invalid fragment specifier `{}`", - frag.name + sess.dcx().emit_err( + errors::InvalidFragmentSpecifier { + span, + fragment, + help: VALID_FRAGMENT_NAMES_MSG.into(), + }, ); - sess.dcx() - .struct_span_err(span, msg) - .with_help(VALID_FRAGMENT_NAMES_MSG) - .emit(); token::NonterminalKind::Ident }, ); diff --git a/tests/ui/macros/invalid-fragment-specifier.rs b/tests/ui/macros/invalid-fragment-specifier.rs new file mode 100644 index 00000000000..1daf0a95434 --- /dev/null +++ b/tests/ui/macros/invalid-fragment-specifier.rs @@ -0,0 +1,10 @@ +macro_rules! test { + ($wrong:id) => {}; +} //~^ ERROR: invalid fragment specifier `id` + +// guard against breaking raw identifier diagnostic +macro_rules! test_raw_identifer { + ($wrong:r#if) => {}; +} //~^ ERROR: invalid fragment specifier `r#if` + +fn main() {} diff --git a/tests/ui/macros/invalid-fragment-specifier.stderr b/tests/ui/macros/invalid-fragment-specifier.stderr new file mode 100644 index 00000000000..7516dbc3a08 --- /dev/null +++ b/tests/ui/macros/invalid-fragment-specifier.stderr @@ -0,0 +1,18 @@ +error: invalid fragment specifier `id` + --> $DIR/invalid-fragment-specifier.rs:2:6 + | +LL | ($wrong:id) => {}; + | ^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: invalid fragment specifier `r#if` + --> $DIR/invalid-fragment-specifier.rs:7:6 + | +LL | ($wrong:r#if) => {}; + | ^^^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/macro-invalid-fragment-spec.rs b/tests/ui/macros/macro-invalid-fragment-spec.rs deleted file mode 100644 index dc4d75096af..00000000000 --- a/tests/ui/macros/macro-invalid-fragment-spec.rs +++ /dev/null @@ -1,8 +0,0 @@ -macro_rules! foo( - ($x:foo) => () - //~^ ERROR invalid fragment specifier -); - -fn main() { - foo!(foo); -} diff --git a/tests/ui/macros/macro-invalid-fragment-spec.stderr b/tests/ui/macros/macro-invalid-fragment-spec.stderr deleted file mode 100644 index 919111ede51..00000000000 --- a/tests/ui/macros/macro-invalid-fragment-spec.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: invalid fragment specifier `foo` - --> $DIR/macro-invalid-fragment-spec.rs:2:6 - | -LL | ($x:foo) => () - | ^^^^^^ - | - = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` - -error: aborting due to 1 previous error -