diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 10d48a55bb54e..ad086eb2c499c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -698,7 +698,13 @@ pub enum NonterminalKind { /// edition of the span. This is used for diagnostics. inferred: bool, }, - Expr, + /// Expr202x with exceptions for const and let not being allowed at the start + Expr2015 { + inferred: bool, + }, + Expr202x { + inferred: bool, + }, Ty, Ident, Lifetime, @@ -728,7 +734,9 @@ impl NonterminalKind { }, sym::pat2015 => NonterminalKind::Pat2015 { inferred: false }, sym::pat2021 => NonterminalKind::Pat2021 { inferred: false }, - sym::expr => NonterminalKind::Expr, + sym::expr => NonterminalKind::Expr2015 { inferred: true }, + sym::expr2015 => NonterminalKind::Expr2015 { inferred: false }, + sym::expr202x => NonterminalKind::Expr202x { inferred: false }, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -749,7 +757,10 @@ impl NonterminalKind { NonterminalKind::Pat2021 { inferred: false } => sym::pat2021, NonterminalKind::Pat2015 { inferred: true } | NonterminalKind::Pat2021 { inferred: true } => sym::pat, - NonterminalKind::Expr => sym::expr, + NonterminalKind::Expr2015 { inferred: false } => sym::expr2015, + NonterminalKind::Expr202x { inferred: false } => sym::expr202x, + NonterminalKind::Expr2015 { inferred: true } + | NonterminalKind::Expr202x { inferred: true } => sym::expr, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index bc45c57596e15..8581f416705b7 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1095,7 +1095,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt | NonterminalKind::Expr => { + NonterminalKind::Stmt + | NonterminalKind::Expr2015 { .. } + | NonterminalKind::Expr202x { .. } => { 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 e205cb65d0229..ea6f001c19403 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -63,16 +63,27 @@ pub(super) fn parse( let span = token.span.with_lo(start_sp.lo()); match frag.name { - sym::pat2015 | sym::pat2021 => { - if !features.edition_macro_pats { - feature_err( - sess, - sym::edition_macro_pats, - frag.span, - "`pat2015` and `pat2021` are unstable.", - ) - .emit(); - } + sym::pat2015 | sym::pat2021 + if !features.edition_macro_pats => + { + feature_err( + sess, + sym::edition_macro_pats, + frag.span, + "`pat2015` and `pat2021` are unstable.", + ) + .emit(); + } + sym::expr2015 | sym::expr202x + if !features.edition_macro_expr => + { + feature_err( + sess, + sym::edition_macro_expr, + frag.span, + "`expr2015` and `expr202x` are unstable.", + ) + .emit(); } _ => {} } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7ae7e0094c6d1..425e28e68e065 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -532,7 +532,7 @@ declare_features! ( /// Allows the use of `no_sanitize` attribute. (active, no_sanitize, "1.42.0", Some(39699), None), - // Allows limiting the evaluation steps of const expressions + /// Allows limiting the evaluation steps of const expressions (active, const_eval_limit, "1.43.0", Some(67217), None), /// Allow negative trait implementations. @@ -655,6 +655,9 @@ declare_features! ( /// Allows unsizing coercions in `const fn`. (active, const_fn_unsize, "1.53.0", Some(64992), None), + /// `:expr2015` and `:expr202x` macro matchers. + (active, edition_macro_expr, "1.53.0", None, None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 5c4a2785d6e26..40e45d0767e4e 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -24,13 +24,14 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr => { + NonterminalKind::Expr2015 { .. } => { 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::Expr202x { .. } => token.can_begin_expr(), NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), NonterminalKind::Literal => token.can_begin_literal_maybe_minus(), @@ -128,7 +129,9 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?), + NonterminalKind::Expr2015 { .. } | NonterminalKind::Expr202x { .. } => { + token::NtExpr(self.parse_expr_force_collect()?) + } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes token::NtLiteral( diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4be187c5208cd..c865971ba6179 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -496,6 +496,7 @@ symbols! { dylib, dyn_metadata, dyn_trait, + edition_macro_expr, edition_macro_pats, eh_catch_typeinfo, eh_personality, @@ -526,6 +527,8 @@ symbols! { expf64, export_name, expr, + expr2015, + expr202x, extended_key_value_attributes, extern_absolute_paths, extern_crate_item_prelude, diff --git a/src/test/ui/feature-gates/feature-gate-edition_macro_expr.rs b/src/test/ui/feature-gates/feature-gate-edition_macro_expr.rs new file mode 100644 index 0000000000000..22001f1b03dbf --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-edition_macro_expr.rs @@ -0,0 +1,8 @@ +// feature gate test for edition_macro_expr + +macro_rules! mac { + ($x:expr2015) => {}; //~ERROR `expr2015` and `expr202x` are unstable + ($x:expr202x) => {}; //~ERROR `expr2015` and `expr202x` are unstable +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-edition_macro_expr.stderr b/src/test/ui/feature-gates/feature-gate-edition_macro_expr.stderr new file mode 100644 index 0000000000000..0fec46cd53785 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-edition_macro_expr.stderr @@ -0,0 +1,19 @@ +error[E0658]: `expr2015` and `expr202x` are unstable. + --> $DIR/feature-gate-edition_macro_expr.rs:4:9 + | +LL | ($x:expr2015) => {}; + | ^^^^^^^^ + | + = help: add `#![feature(edition_macro_expr)]` to the crate attributes to enable + +error[E0658]: `expr2015` and `expr202x` are unstable. + --> $DIR/feature-gate-edition_macro_expr.rs:5:9 + | +LL | ($x:expr202x) => {}; + | ^^^^^^^^ + | + = help: add `#![feature(edition_macro_expr)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/macro-expr2015-matching.rs b/src/test/ui/macros/macro-expr2015-matching.rs new file mode 100644 index 0000000000000..cf8ff3c815406 --- /dev/null +++ b/src/test/ui/macros/macro-expr2015-matching.rs @@ -0,0 +1,34 @@ +// run-pass + +#![feature(edition_macro_expr)] +#![feature(inline_const)] +#![allow(incomplete_features)] + +macro_rules! new_const { + ($e:expr202x) => { + $e + }; + (const $e:block) => { + 1 + }; +} + +macro_rules! old_const { + ($e:expr2015) => { + $e + }; + (const $e:block) => { + 1 + }; +} + +fn main() { + match 1 { + old_const!(const { 2 }) => (), + _ => unreachable!(), + } + match 1 { + new_const!(const { 2 }) => unreachable!(), + _ => (), + } +}