Skip to content

Commit dbb3841

Browse files
committed
Add expr202x macro pattern
This makes it possible to use `inline_const` (rust-lang#76001) and `let_chains` (rust-lang#53667) inside macros' `expr` patterns in a future edition by bifurcating the `expr` nonterminal in a similar way to `pat2021` to remove some backwards compatibility exceptions that disallow `const`/`let` at the beginning of an `expr` match. Fixes rust-lang#84155 and relaxes the backward compat restriction from rust-lang#80135 for a future edition. This is not intended to go into 2021 as it I don't think it's simple to write an automatic fix, and certainly not now that it's past the soft deadline for inclusion in 2021 by a long shot. Here is a pathological case of rust-lang#79908 that forces this to be an edition change: ```rust macro_rules! evil { ($e:expr) => { // or something else const {$e-1} }; (const $b:block) => { const {$b} } } fn main() { let x = 5; match x { evil!(const { 5 }) => panic!("oh no"), _ => (), }; } ```
1 parent f8f5968 commit dbb3841

File tree

9 files changed

+111
-17
lines changed

9 files changed

+111
-17
lines changed

compiler/rustc_ast/src/token.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,13 @@ pub enum NonterminalKind {
698698
/// edition of the span. This is used for diagnostics.
699699
inferred: bool,
700700
},
701-
Expr,
701+
/// Expr202x with exceptions for const and let not being allowed at the start
702+
Expr2015 {
703+
inferred: bool,
704+
},
705+
Expr202x {
706+
inferred: bool,
707+
},
702708
Ty,
703709
Ident,
704710
Lifetime,
@@ -728,7 +734,9 @@ impl NonterminalKind {
728734
},
729735
sym::pat2015 => NonterminalKind::Pat2015 { inferred: false },
730736
sym::pat2021 => NonterminalKind::Pat2021 { inferred: false },
731-
sym::expr => NonterminalKind::Expr,
737+
sym::expr => NonterminalKind::Expr2015 { inferred: true },
738+
sym::expr2015 => NonterminalKind::Expr2015 { inferred: false },
739+
sym::expr202x => NonterminalKind::Expr202x { inferred: false },
732740
sym::ty => NonterminalKind::Ty,
733741
sym::ident => NonterminalKind::Ident,
734742
sym::lifetime => NonterminalKind::Lifetime,
@@ -749,7 +757,10 @@ impl NonterminalKind {
749757
NonterminalKind::Pat2021 { inferred: false } => sym::pat2021,
750758
NonterminalKind::Pat2015 { inferred: true }
751759
| NonterminalKind::Pat2021 { inferred: true } => sym::pat,
752-
NonterminalKind::Expr => sym::expr,
760+
NonterminalKind::Expr2015 { inferred: false } => sym::expr2015,
761+
NonterminalKind::Expr202x { inferred: false } => sym::expr202x,
762+
NonterminalKind::Expr2015 { inferred: true }
763+
| NonterminalKind::Expr202x { inferred: true } => sym::expr,
753764
NonterminalKind::Ty => sym::ty,
754765
NonterminalKind::Ident => sym::ident,
755766
NonterminalKind::Lifetime => sym::lifetime,

compiler/rustc_expand/src/mbe/macro_rules.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
10951095
// maintain
10961096
IsInFollow::Yes
10971097
}
1098-
NonterminalKind::Stmt | NonterminalKind::Expr => {
1098+
NonterminalKind::Stmt
1099+
| NonterminalKind::Expr2015 { .. }
1100+
| NonterminalKind::Expr202x { .. } => {
10991101
const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
11001102
match tok {
11011103
TokenTree::Token(token) => match token.kind {

compiler/rustc_expand/src/mbe/quoted.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,27 @@ pub(super) fn parse(
6363
let span = token.span.with_lo(start_sp.lo());
6464

6565
match frag.name {
66-
sym::pat2015 | sym::pat2021 => {
67-
if !features.edition_macro_pats {
68-
feature_err(
69-
sess,
70-
sym::edition_macro_pats,
71-
frag.span,
72-
"`pat2015` and `pat2021` are unstable.",
73-
)
74-
.emit();
75-
}
66+
sym::pat2015 | sym::pat2021
67+
if !features.edition_macro_pats =>
68+
{
69+
feature_err(
70+
sess,
71+
sym::edition_macro_pats,
72+
frag.span,
73+
"`pat2015` and `pat2021` are unstable.",
74+
)
75+
.emit();
76+
}
77+
sym::expr2015 | sym::expr202x
78+
if !features.edition_macro_expr =>
79+
{
80+
feature_err(
81+
sess,
82+
sym::edition_macro_expr,
83+
frag.span,
84+
"`expr2015` and `expr202x` are unstable.",
85+
)
86+
.emit();
7687
}
7788
_ => {}
7889
}

compiler/rustc_feature/src/active.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ declare_features! (
532532
/// Allows the use of `no_sanitize` attribute.
533533
(active, no_sanitize, "1.42.0", Some(39699), None),
534534

535-
// Allows limiting the evaluation steps of const expressions
535+
/// Allows limiting the evaluation steps of const expressions
536536
(active, const_eval_limit, "1.43.0", Some(67217), None),
537537

538538
/// Allow negative trait implementations.
@@ -655,6 +655,9 @@ declare_features! (
655655
/// Allows unsizing coercions in `const fn`.
656656
(active, const_fn_unsize, "1.53.0", Some(64992), None),
657657

658+
/// `:expr2015` and `:expr202x` macro matchers.
659+
(active, edition_macro_expr, "1.53.0", None, None),
660+
658661
// -------------------------------------------------------------------------
659662
// feature-group-end: actual feature gates
660663
// -------------------------------------------------------------------------

compiler/rustc_parse/src/parser/nonterminal.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ impl<'a> Parser<'a> {
2424
}
2525

2626
match kind {
27-
NonterminalKind::Expr => {
27+
NonterminalKind::Expr2015 { .. } => {
2828
token.can_begin_expr()
2929
// This exception is here for backwards compatibility.
3030
&& !token.is_keyword(kw::Let)
3131
// This exception is here for backwards compatibility.
3232
&& !token.is_keyword(kw::Const)
3333
}
34+
NonterminalKind::Expr202x { .. } => token.can_begin_expr(),
3435
NonterminalKind::Ty => token.can_begin_type(),
3536
NonterminalKind::Ident => get_macro_ident(token).is_some(),
3637
NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
@@ -128,7 +129,9 @@ impl<'a> Parser<'a> {
128129
})?)
129130
}
130131

131-
NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?),
132+
NonterminalKind::Expr2015 { .. } | NonterminalKind::Expr202x { .. } => {
133+
token::NtExpr(self.parse_expr_force_collect()?)
134+
}
132135
NonterminalKind::Literal => {
133136
// The `:literal` matcher does not support attributes
134137
token::NtLiteral(

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ symbols! {
496496
dylib,
497497
dyn_metadata,
498498
dyn_trait,
499+
edition_macro_expr,
499500
edition_macro_pats,
500501
eh_catch_typeinfo,
501502
eh_personality,
@@ -526,6 +527,8 @@ symbols! {
526527
expf64,
527528
export_name,
528529
expr,
530+
expr2015,
531+
expr202x,
529532
extended_key_value_attributes,
530533
extern_absolute_paths,
531534
extern_crate_item_prelude,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// feature gate test for edition_macro_expr
2+
3+
macro_rules! mac {
4+
($x:expr2015) => {}; //~ERROR `expr2015` and `expr202x` are unstable
5+
($x:expr202x) => {}; //~ERROR `expr2015` and `expr202x` are unstable
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0658]: `expr2015` and `expr202x` are unstable.
2+
--> $DIR/feature-gate-edition_macro_expr.rs:4:9
3+
|
4+
LL | ($x:expr2015) => {};
5+
| ^^^^^^^^
6+
|
7+
= help: add `#![feature(edition_macro_expr)]` to the crate attributes to enable
8+
9+
error[E0658]: `expr2015` and `expr202x` are unstable.
10+
--> $DIR/feature-gate-edition_macro_expr.rs:5:9
11+
|
12+
LL | ($x:expr202x) => {};
13+
| ^^^^^^^^
14+
|
15+
= help: add `#![feature(edition_macro_expr)]` to the crate attributes to enable
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// run-pass
2+
3+
#![feature(edition_macro_expr)]
4+
#![feature(inline_const)]
5+
#![allow(incomplete_features)]
6+
7+
macro_rules! new_const {
8+
($e:expr202x) => {
9+
$e
10+
};
11+
(const $e:block) => {
12+
1
13+
};
14+
}
15+
16+
macro_rules! old_const {
17+
($e:expr2015) => {
18+
$e
19+
};
20+
(const $e:block) => {
21+
1
22+
};
23+
}
24+
25+
fn main() {
26+
match 1 {
27+
old_const!(const { 2 }) => (),
28+
_ => unreachable!(),
29+
}
30+
match 1 {
31+
new_const!(const { 2 }) => unreachable!(),
32+
_ => (),
33+
}
34+
}

0 commit comments

Comments
 (0)