mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #129972 - eholk:stabilize-expr_2021, r=compiler-errors,traviscross
Stabilize expr_2021 fragment specifier in all editions This is part of the `expr`/`expr_2021` fragment specifier for Edition 2024 (#123742). The RFC says we can support expr_2021 in as many editions as is practical, and there's nothing particularly hard about supporting it all the way back to 2015. In editions 2021 and earlier, `expr` and `expr_2021` are synonyms. Their behavior diverges starting in Edition 2024. This is checked by the `expr_2021_inline_const.rs` test. cc `@vincenzopalazzo` `@rust-lang/wg-macros` `@traviscross`
This commit is contained in:
commit
21aa500bb0
@ -119,7 +119,7 @@ use rustc_span::symbol::{MacroRulesNormalizedIdent, kw};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use super::quoted::VALID_FRAGMENT_NAMES_MSG_2021;
|
||||
use super::quoted::VALID_FRAGMENT_NAMES_MSG;
|
||||
use crate::errors;
|
||||
use crate::mbe::{KleeneToken, TokenTree};
|
||||
|
||||
@ -274,7 +274,7 @@ fn check_binders(
|
||||
psess.dcx().emit_err(errors::MissingFragmentSpecifier {
|
||||
span,
|
||||
add_span: span.shrink_to_hi(),
|
||||
valid: VALID_FRAGMENT_NAMES_MSG_2021,
|
||||
valid: VALID_FRAGMENT_NAMES_MSG,
|
||||
});
|
||||
} else {
|
||||
psess.buffer_lint(
|
||||
|
@ -1,4 +1,3 @@
|
||||
use rustc_ast::token::NtExprKind::*;
|
||||
use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token};
|
||||
use rustc_ast::{NodeId, tokenstream};
|
||||
use rustc_ast_pretty::pprust;
|
||||
@ -13,12 +12,9 @@ use crate::errors;
|
||||
use crate::mbe::macro_parser::count_metavar_decls;
|
||||
use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
|
||||
|
||||
const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
|
||||
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \
|
||||
`item` and `vis`";
|
||||
pub(crate) 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`";
|
||||
pub(crate) const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
|
||||
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, \
|
||||
`meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility";
|
||||
|
||||
/// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this
|
||||
/// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a
|
||||
@ -92,39 +88,13 @@ pub(super) fn parse(
|
||||
};
|
||||
let kind = 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,
|
||||
help: VALID_FRAGMENT_NAMES_MSG.into(),
|
||||
});
|
||||
NonterminalKind::Ident
|
||||
});
|
||||
if kind == NonterminalKind::Expr(Expr2021 { inferred: false })
|
||||
&& !features.expr_fragment_specifier_2024
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -189,6 +189,8 @@ declare_features! (
|
||||
(accepted, exhaustive_integer_patterns, "1.33.0", Some(50907)),
|
||||
/// Allows explicit generic arguments specification with `impl Trait` present.
|
||||
(accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701)),
|
||||
/// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment.
|
||||
(accepted, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)),
|
||||
/// Allows arbitrary expressions in key-value attributes at parse time.
|
||||
(accepted, extended_key_value_attributes, "1.54.0", Some(78835)),
|
||||
/// Allows resolving absolute paths as paths from other crates.
|
||||
|
@ -450,8 +450,6 @@ 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, "1.80.0", 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)),
|
||||
|
@ -4,7 +4,7 @@ error: invalid fragment specifier `t_ty`
|
||||
LL | ($wrong:t_ty) => ()
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
14
tests/ui/macros/expr_2021.rs
Normal file
14
tests/ui/macros/expr_2021.rs
Normal file
@ -0,0 +1,14 @@
|
||||
//@ check-pass
|
||||
//@ edition: 2015
|
||||
|
||||
// Ensures expr_2021 fragment specifier is accepted in old editions
|
||||
|
||||
macro_rules! my_macro {
|
||||
($x:expr_2021) => {
|
||||
println!("Hello, {}!", $x);
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
my_macro!("world");
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
//@ run-rustfix
|
||||
//@ check-pass
|
||||
//@ compile-flags: --edition=2021
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(expr_fragment_specifier_2024)]
|
||||
#![warn(edition_2024_expr_fragment_specifier)]
|
||||
|
||||
macro_rules! m {
|
||||
|
@ -1,8 +1,6 @@
|
||||
//@ run-rustfix
|
||||
//@ check-pass
|
||||
//@ compile-flags: --edition=2021
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(expr_fragment_specifier_2024)]
|
||||
#![warn(edition_2024_expr_fragment_specifier)]
|
||||
|
||||
macro_rules! m {
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: the `expr` fragment specifier will accept more expressions in the 2024 edition
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:9:9
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:7:9
|
||||
|
|
||||
LL | ($e:expr) => {
|
||||
| ^^^^
|
||||
@ -7,7 +7,7 @@ LL | ($e:expr) => {
|
||||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see Migration Guide <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/macro-fragment-specifiers.html>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:6:9
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:4:9
|
||||
|
|
||||
LL | #![warn(edition_2024_expr_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -17,7 +17,7 @@ LL | ($e:expr_2021) => {
|
||||
| ~~~~~~~~~
|
||||
|
||||
warning: the `expr` fragment specifier will accept more expressions in the 2024 edition
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:13:11
|
||||
--> $DIR/expr_2021_cargo_fix_edition.rs:11:11
|
||||
|
|
||||
LL | ($($i:expr)*) => { };
|
||||
| ^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: no rules expected the token `const`
|
||||
--> $DIR/expr_2021_inline_const.rs:26:12
|
||||
--> $DIR/expr_2021_inline_const.rs:23:12
|
||||
|
|
||||
LL | macro_rules! m2021 {
|
||||
| ------------------ when calling this macro
|
||||
@ -8,13 +8,13 @@ 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
|
||||
--> $DIR/expr_2021_inline_const.rs:7:6
|
||||
|
|
||||
LL | ($e:expr_2021) => {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: no rules expected the token `const`
|
||||
--> $DIR/expr_2021_inline_const.rs:27:12
|
||||
--> $DIR/expr_2021_inline_const.rs:24:12
|
||||
|
|
||||
LL | macro_rules! m2024 {
|
||||
| ------------------ when calling this macro
|
||||
@ -23,7 +23,7 @@ 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
|
||||
--> $DIR/expr_2021_inline_const.rs:13:6
|
||||
|
|
||||
LL | ($e:expr) => {
|
||||
| ^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: no rules expected the token `const`
|
||||
--> $DIR/expr_2021_inline_const.rs:26:12
|
||||
--> $DIR/expr_2021_inline_const.rs:23:12
|
||||
|
|
||||
LL | macro_rules! m2021 {
|
||||
| ------------------ when calling this macro
|
||||
@ -8,7 +8,7 @@ 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
|
||||
--> $DIR/expr_2021_inline_const.rs:7:6
|
||||
|
|
||||
LL | ($e:expr_2021) => {
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -3,9 +3,6 @@
|
||||
//@[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
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: no rules expected the token `_`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:22:12
|
||||
--> $DIR/expr_2024_underscore_expr.rs:19:12
|
||||
|
|
||||
LL | macro_rules! m2021 {
|
||||
| ------------------ when calling this macro
|
||||
@ -8,13 +8,13 @@ LL | m2021!(_);
|
||||
| ^ no rules expected this token in macro call
|
||||
|
|
||||
note: while trying to match meta-variable `$e:expr_2021`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:10:6
|
||||
--> $DIR/expr_2024_underscore_expr.rs:7:6
|
||||
|
|
||||
LL | ($e:expr_2021) => {
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: no rules expected the token `_`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:23:12
|
||||
--> $DIR/expr_2024_underscore_expr.rs:20:12
|
||||
|
|
||||
LL | macro_rules! m2024 {
|
||||
| ------------------ when calling this macro
|
||||
@ -23,7 +23,7 @@ LL | m2024!(_);
|
||||
| ^ no rules expected this token in macro call
|
||||
|
|
||||
note: while trying to match meta-variable `$e:expr`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:16:6
|
||||
--> $DIR/expr_2024_underscore_expr.rs:13:6
|
||||
|
|
||||
LL | ($e:expr) => {
|
||||
| ^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: no rules expected the token `_`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:22:12
|
||||
--> $DIR/expr_2024_underscore_expr.rs:19:12
|
||||
|
|
||||
LL | macro_rules! m2021 {
|
||||
| ------------------ when calling this macro
|
||||
@ -8,7 +8,7 @@ LL | m2021!(_);
|
||||
| ^ no rules expected this token in macro call
|
||||
|
|
||||
note: while trying to match meta-variable `$e:expr_2021`
|
||||
--> $DIR/expr_2024_underscore_expr.rs:10:6
|
||||
--> $DIR/expr_2024_underscore_expr.rs:7:6
|
||||
|
|
||||
LL | ($e:expr_2021) => {
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -3,9 +3,6 @@
|
||||
//@[edi2021]compile-flags: --edition=2021
|
||||
// This test ensures that the `_` tok is considered an
|
||||
// expression on edition 2024.
|
||||
#![feature(expr_fragment_specifier_2024)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
macro_rules! m2021 {
|
||||
($e:expr_2021) => {
|
||||
$e = 1;
|
||||
|
@ -1,11 +0,0 @@
|
||||
//@ compile-flags: --edition=2024 -Z unstable-options
|
||||
|
||||
macro_rules! m {
|
||||
($e:expr_2021) => { //~ ERROR: fragment specifier `expr_2021` is unstable
|
||||
$e
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
m!(());
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
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 <https://github.com/rust-lang/rust/issues/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`.
|
@ -4,7 +4,7 @@ error: invalid fragment specifier `id`
|
||||
LL | ($wrong:id) => {};
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
|
||||
error: invalid fragment specifier `r#if`
|
||||
--> $DIR/invalid-fragment-specifier.rs:7:6
|
||||
@ -12,7 +12,7 @@ error: invalid fragment specifier `r#if`
|
||||
LL | ($wrong:r#if) => {};
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,7 +4,7 @@ error: invalid fragment specifier `t_ty`
|
||||
LL | macro_rules! test { ($wrong:t_ty ..) => () }
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type:spec )* ) => {};
|
||||
@ -18,7 +18,7 @@ LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ( $name:spec ) => {};
|
||||
@ -31,7 +31,7 @@ LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ( $name:spec ) => {};
|
||||
|
@ -6,7 +6,6 @@
|
||||
// This test captures the behavior of macro-generating-macros with fragment
|
||||
// specifiers across edition boundaries.
|
||||
|
||||
#![feature(expr_fragment_specifier_2024)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user