From ef6478ba5fde1a1ed6db27fc7f558bc26e38d781 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 12 Apr 2024 10:19:23 -0700 Subject: [PATCH 1/6] Add expr_2021 nonterminal and feature flag This commit adds a new nonterminal `expr_2021` in macro patterns, and `expr_fragment_specifier_2024` feature flag. For now, `expr` and `expr_2021` are treated the same, but in future PRs we will update `expr` to match to new grammar. Co-authored-by: Vincezo Palazzo --- compiler/rustc_ast/src/token.rs | 4 ++++ compiler/rustc_expand/messages.ftl | 3 +++ compiler/rustc_expand/src/errors.rs | 7 +++++++ compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_expand/src/mbe/quoted.rs | 6 ++++++ compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_parse/src/parser/nonterminal.rs | 6 ++++-- compiler/rustc_span/src/symbol.rs | 2 ++ .../feature-gate-expr_fragment_specifier_2024.rs | 11 +++++++++++ .../feature-gate-expr_fragment_specifier_2024.stderr | 8 ++++++++ 10 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs create mode 100644 tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 72f89737f9952..0b741c2cc40e5 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 b7aae2af9ef97..73babf5d324d8 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 b0563bfdea749..bc91dfe7a8885 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 470bde232d723..71daaacd0567f 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 06c1612ddbaea..5508c0d0503c4 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 60b386acf9106..c6fc9de119dc4 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 73b17353ac90c..dc51d85792cf3 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 d41059e8c24a4..68b1b32baf2dc 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 0000000000000..fff1ea34d83e6 --- /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 0000000000000..078ff57a971f1 --- /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 + From 65da4adfcd12a062874524a37ebd4f522c04205f Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 12 Apr 2024 10:28:03 -0700 Subject: [PATCH 2/6] Add test that expr_2021 only works on 2024 edition Co-authored-by: Vincenzo Palazzo --- tests/ui/macros/expr_2021_old_edition.rs | 13 ++++++++++ tests/ui/macros/expr_2021_old_edition.stderr | 25 ++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/ui/macros/expr_2021_old_edition.rs create mode 100644 tests/ui/macros/expr_2021_old_edition.stderr diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs new file mode 100644 index 0000000000000..329c5cdca3355 --- /dev/null +++ b/tests/ui/macros/expr_2021_old_edition.rs @@ -0,0 +1,13 @@ +//@ compile-flags: --edition=2021 + +// This test ensures that expr_2021 is not allowed on pre-2024 editions + +macro_rules! m { + ($e:expr_2021) => { //~ ERROR: invalid fragment specifier `expr_2021` + $e + }; +} + +fn main() { + m!(()); //~ ERROR: no rules expected the token `(` +} diff --git a/tests/ui/macros/expr_2021_old_edition.stderr b/tests/ui/macros/expr_2021_old_edition.stderr new file mode 100644 index 0000000000000..b5934fb3361b2 --- /dev/null +++ b/tests/ui/macros/expr_2021_old_edition.stderr @@ -0,0 +1,25 @@ +error: invalid fragment specifier `expr_2021` + --> $DIR/expr_2021_old_edition.rs:6:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + | + = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + +error: no rules expected the token `(` + --> $DIR/expr_2021_old_edition.rs:12:8 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(()); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:ident` + --> $DIR/expr_2021_old_edition.rs:6:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 73303c3b454379772053957d88437277a121c173 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 16 Apr 2024 10:31:21 -0700 Subject: [PATCH 3/6] expr_2021 should be allowed on edition 2021 and later --- compiler/rustc_ast/src/token.rs | 2 +- tests/ui/macros/expr_2021_old_edition.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 0b741c2cc40e5..bbab13221d397 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -909,7 +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::expr_2021 if edition() >= Edition::Edition2021 => NonterminalKind::Expr2021, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs index 329c5cdca3355..ab7999ab3731f 100644 --- a/tests/ui/macros/expr_2021_old_edition.rs +++ b/tests/ui/macros/expr_2021_old_edition.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ compile-flags: --edition=2018 // This test ensures that expr_2021 is not allowed on pre-2024 editions From a55d06323aef19040aba222b7ede790291e08468 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Tue, 16 Apr 2024 20:47:10 +0200 Subject: [PATCH 4/6] Macros: match const { ... } with expr nonterminal in edition 2024 Co-authored-by: Eric Holk Signed-off-by: Vincenzo Palazzo --- .../rustc_parse/src/parser/nonterminal.rs | 9 +++++- .../expr_2021_inline_const.edi2021.stderr | 32 +++++++++++++++++++ .../expr_2021_inline_const.edi2024.stderr | 17 ++++++++++ tests/ui/macros/expr_2021_inline_const.rs | 23 +++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/expr_2021_inline_const.edi2021.stderr create mode 100644 tests/ui/macros/expr_2021_inline_const.edi2024.stderr create mode 100644 tests/ui/macros/expr_2021_inline_const.rs diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index dc51d85792cf3..8c0f295b74bc3 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -3,6 +3,7 @@ use rustc_ast::token::{self, Delimiter, Nonterminal, Nonterminal::*, Nonterminal use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_errors::PResult; +use rustc_span::edition::Edition; use rustc_span::symbol::{kw, Ident}; use crate::errors::UnexpectedNonterminal; @@ -37,13 +38,19 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NonterminalKind::Expr2021 => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } + NonterminalKind::Expr => { + token.can_begin_expr() + // This exception is here for backwards compatibility. + && !token.is_keyword(kw::Let) + && (token.span.edition() >= Edition::Edition2024 || !token.is_keyword(kw::Const)) + } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), diff --git a/tests/ui/macros/expr_2021_inline_const.edi2021.stderr b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr new file mode 100644 index 0000000000000..5e88096445473 --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.edi2021.stderr @@ -0,0 +1,32 @@ +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:21:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2021_inline_const.rs:10:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:22:12 + | +LL | macro_rules! m2024 { + | ------------------ when calling this macro +... +LL | m2024!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/expr_2021_inline_const.rs:16:6 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/expr_2021_inline_const.edi2024.stderr b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr new file mode 100644 index 0000000000000..237ecb2cc192a --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.edi2024.stderr @@ -0,0 +1,17 @@ +error: no rules expected the token `const` + --> $DIR/expr_2021_inline_const.rs:21:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(const { 1 }); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2021_inline_const.rs:10:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/expr_2021_inline_const.rs b/tests/ui/macros/expr_2021_inline_const.rs new file mode 100644 index 0000000000000..ebc5ea3642108 --- /dev/null +++ b/tests/ui/macros/expr_2021_inline_const.rs @@ -0,0 +1,23 @@ +//@ revisions: edi2021 edi2024 +//@[edi2024]compile-flags: --edition=2024 -Z unstable-options +//@[edi2021]compile-flags: --edition=2021 + +// This test ensures that the inline const match only on edition 2024 +#![feature(expr_fragment_specifier_2024)] +#![allow(incomplete_features)] + +macro_rules! m2021 { + ($e:expr_2021) => { + $e + }; +} + +macro_rules! m2024 { + ($e:expr) => { + $e + }; +} +fn main() { + m2021!(const { 1 }); //~ ERROR: no rules expected the token `const` + m2024!(const { 1 }); //[edi2021]~ ERROR: no rules expected the token `const` +} From f364011955f8316f897cc0a2a930b8665d918177 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 30 Apr 2024 16:32:26 -0700 Subject: [PATCH 5/6] Apply code review suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use feature_err to report unstable expr_2021 - Update downlevel expr_2021 diagnostics Co-authored-by: León Orell Valerian Liehr --- compiler/rustc_ast/src/token.rs | 2 +- compiler/rustc_expand/messages.ftl | 3 - compiler/rustc_expand/src/errors.rs | 7 -- compiler/rustc_expand/src/mbe/quoted.rs | 69 ++++++++++++------- tests/ui/macros/expr_2021_old_edition.rs | 2 +- tests/ui/macros/expr_2021_old_edition.stderr | 3 +- ...ature-gate-expr_fragment_specifier_2024.rs | 2 +- ...e-gate-expr_fragment_specifier_2024.stderr | 7 +- 8 files changed, 57 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index bbab13221d397..e44725e7f15ba 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -909,7 +909,7 @@ impl NonterminalKind { }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, - sym::expr_2021 if edition() >= Edition::Edition2021 => NonterminalKind::Expr2021, + sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 73babf5d324d8..b7aae2af9ef97 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -39,9 +39,6 @@ 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 bc91dfe7a8885..b0563bfdea749 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -433,10 +433,3 @@ 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/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 5508c0d0503c4..e67955be3d6d2 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -16,6 +16,10 @@ use rustc_span::Span; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ `literal`, `path`, `meta`, `tt`, `item` and `vis`"; +const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \ + `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \ + `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \ + `item` and `vis`"; /// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a @@ -63,40 +67,59 @@ pub(super) fn parse( Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { let span = token.span.with_lo(start_sp.lo()); - + let edition = || { + // FIXME(#85708) - once we properly decode a foreign + // crate's `SyntaxContext::root`, then we can replace + // this with just `span.edition()`. A + // `SyntaxContext::root()` from the current crate will + // have the edition of the current crate, and a + // `SyntaxContext::root()` from a foreign crate will + // have the edition of that crate (which we manually + // retrieve via the `edition` parameter). + if !span.from_expansion() { + edition + } else { + span.edition() + } + }; let kind = - 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 - // `SyntaxContext::root()` from the current crate will - // have the edition of the current crate, and a - // `SyntaxContext::root()` from a foreign crate will - // have the edition of that crate (which we manually - // retrieve via the `edition` parameter). - if !span.from_expansion() { - edition - } else { - span.edition() - } - }) - .unwrap_or_else( - || { + token::NonterminalKind::from_symbol(fragment.name, edition) + .unwrap_or_else(|| { + let help = match fragment.name { + sym::expr_2021 => { + format!( + "fragment specifier `expr_2021` \ + requires Rust 2021 or later\n\ + {VALID_FRAGMENT_NAMES_MSG}" + ) + } + _ if edition().at_least_rust_2021() + && features + .expr_fragment_specifier_2024 => + { + VALID_FRAGMENT_NAMES_MSG_2021.into() + } + _ => VALID_FRAGMENT_NAMES_MSG.into(), + }; sess.dcx().emit_err( errors::InvalidFragmentSpecifier { span, fragment, - help: VALID_FRAGMENT_NAMES_MSG.into(), + help, }, ); token::NonterminalKind::Ident - }, - ); + }); if kind == token::NonterminalKind::Expr2021 && !features.expr_fragment_specifier_2024 { - sess.dcx() - .emit_err(errors::Expr2021IsExperimental { span }); + rustc_session::parse::feature_err( + sess, + sym::expr_fragment_specifier_2024, + span, + "fragment specifier `expr_2021` is unstable", + ) + .emit(); } result.push(TokenTree::MetaVarDecl(span, ident, Some(kind))); continue; diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs index ab7999ab3731f..a771126610686 100644 --- a/tests/ui/macros/expr_2021_old_edition.rs +++ b/tests/ui/macros/expr_2021_old_edition.rs @@ -1,6 +1,6 @@ //@ compile-flags: --edition=2018 -// This test ensures that expr_2021 is not allowed on pre-2024 editions +// This test ensures that expr_2021 is not allowed on pre-2021 editions macro_rules! m { ($e:expr_2021) => { //~ ERROR: invalid fragment specifier `expr_2021` diff --git a/tests/ui/macros/expr_2021_old_edition.stderr b/tests/ui/macros/expr_2021_old_edition.stderr index b5934fb3361b2..bffa8a1ca1759 100644 --- a/tests/ui/macros/expr_2021_old_edition.stderr +++ b/tests/ui/macros/expr_2021_old_edition.stderr @@ -4,7 +4,8 @@ error: invalid fragment specifier `expr_2021` LL | ($e:expr_2021) => { | ^^^^^^^^^^^^ | - = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` + = help: fragment specifier `expr_2021` requires Rust 2021 or later + valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` error: no rules expected the token `(` --> $DIR/expr_2021_old_edition.rs:12:8 diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs index fff1ea34d83e6..5a737b298214d 100644 --- a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.rs @@ -1,7 +1,7 @@ //@ compile-flags: --edition=2024 -Z unstable-options macro_rules! m { - ($e:expr_2021) => { //~ ERROR: expr_2021 is experimental + ($e:expr_2021) => { //~ ERROR: fragment specifier `expr_2021` is unstable $e }; } diff --git a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr index 078ff57a971f1..273a93877ce13 100644 --- a/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr +++ b/tests/ui/macros/feature-gate-expr_fragment_specifier_2024.stderr @@ -1,8 +1,13 @@ -error: expr_2021 is experimental +error[E0658]: fragment specifier `expr_2021` is unstable --> $DIR/feature-gate-expr_fragment_specifier_2024.rs:4:6 | LL | ($e:expr_2021) => { | ^^^^^^^^^^^^ + | + = note: see issue #123742 for more information + = help: add `#![feature(expr_fragment_specifier_2024)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0658`. From 3986ea0ea555ab6de8af46932da94c26aa1c28ee Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Fri, 17 May 2024 11:27:18 -0700 Subject: [PATCH 6/6] Update compiler/rustc_parse/src/parser/nonterminal.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: León Orell Valerian Liehr --- compiler/rustc_parse/src/parser/nonterminal.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 8c0f295b74bc3..274157dee57bf 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -3,7 +3,6 @@ use rustc_ast::token::{self, Delimiter, Nonterminal, Nonterminal::*, Nonterminal use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; use rustc_errors::PResult; -use rustc_span::edition::Edition; use rustc_span::symbol::{kw, Ident}; use crate::errors::UnexpectedNonterminal; @@ -49,7 +48,7 @@ impl<'a> Parser<'a> { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) - && (token.span.edition() >= Edition::Edition2024 || !token.is_keyword(kw::Const)) + && (token.span.edition().at_least_rust_2024() || !token.is_keyword(kw::Const)) } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(),