diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 72f89737f99..0b741c2cc40 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -878,6 +878,8 @@ pub enum NonterminalKind { }, PatWithOr, Expr, + /// Matches an expression using the rules from edition 2021 and earlier. + Expr2021, Ty, Ident, Lifetime, @@ -907,6 +909,7 @@ impl NonterminalKind { }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, + sym::expr_2021 if edition() >= Edition::Edition2024 => NonterminalKind::Expr2021, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -926,6 +929,7 @@ impl NonterminalKind { NonterminalKind::PatParam { inferred: false } => sym::pat_param, NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, NonterminalKind::Expr => sym::expr, + NonterminalKind::Expr2021 => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index b7aae2af9ef..73babf5d324 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -39,6 +39,9 @@ expand_explain_doc_comment_inner = expand_explain_doc_comment_outer = outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match +expand_expr_2021_is_experimental = + expr_2021 is experimental + expand_expr_repeat_no_syntax_vars = attempted to repeat an expression containing no syntax variables matched as repeating at this depth diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index b0563bfdea7..bc91dfe7a88 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -433,3 +433,10 @@ pub struct ExpectedParenOrBrace<'a> { pub span: Span, pub token: Cow<'a, str>, } + +#[derive(Diagnostic)] +#[diag(expand_expr_2021_is_experimental)] +pub struct Expr2021IsExperimental { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 470bde232d7..71daaacd056 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1290,7 +1290,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt | NonterminalKind::Expr => { + NonterminalKind::Stmt | NonterminalKind::Expr | NonterminalKind::Expr2021 => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 06c1612ddba..5508c0d0503 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -92,6 +92,12 @@ pub(super) fn parse( token::NonterminalKind::Ident }, ); + if kind == token::NonterminalKind::Expr2021 + && !features.expr_fragment_specifier_2024 + { + sess.dcx() + .emit_err(errors::Expr2021IsExperimental { span }); + } result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); continue; } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 60b386acf91..c6fc9de119d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -458,6 +458,8 @@ declare_features! ( (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), + /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment. + (incomplete, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)), /// Allows using `efiapi`, `sysv64` and `win64` as calling convention /// for functions with varargs. (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 73b17353ac9..dc51d85792c 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -37,7 +37,7 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr => { + NonterminalKind::Expr | NonterminalKind::Expr2021 => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -145,7 +145,9 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NtExpr(self.parse_expr_force_collect()?) + } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d41059e8c24..68b1b32baf2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -782,6 +782,8 @@ symbols! { explicit_tail_calls, export_name, expr, + expr_2021, + expr_fragment_specifier_2024, extended_key_value_attributes, extended_varargs_abi_support, extern_absolute_paths, diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs new file mode 100644 index 00000000000..fff1ea34d83 --- /dev/null +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs @@ -0,0 +1,11 @@ +//@ compile-flags: --edition=2024 -Z unstable-options + +macro_rules! m { + ($e:expr_2021) => { //~ ERROR: expr_2021 is experimental + $e + }; +} + +fn main() { + m!(()); +} diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr new file mode 100644 index 00000000000..078ff57a971 --- /dev/null +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr @@ -0,0 +1,8 @@ +error: expr_2021 is experimental + --> $DIR/feature-gate-expr_fragment_specifier_2024.rs:4:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error +