Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/mbe/src/benchmark.rs2
-rw-r--r--crates/mbe/src/expander/matcher.rs31
-rw-r--r--crates/mbe/src/expander/transcriber.rs2
-rw-r--r--crates/mbe/src/parser.rs32
-rw-r--r--crates/mbe/src/tests.rs146
5 files changed, 192 insertions, 21 deletions
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index 43604eb232..f8c1d027c6 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -146,7 +146,7 @@ fn invocation_fixtures(
Some(MetaVarKind::Pat) => token_trees.push(make_ident("foo")),
Some(MetaVarKind::Path) => token_trees.push(make_ident("foo")),
Some(MetaVarKind::Literal) => token_trees.push(make_literal("1")),
- Some(MetaVarKind::Expr) => token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Expr(_)) => token_trees.push(make_ident("foo")),
Some(MetaVarKind::Lifetime) => {
token_trees.push(make_punct('\''));
token_trees.push(make_ident("a"));
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index e69d7d14e2..90f56cc31d 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -69,7 +69,7 @@ use tt::{iter::TtIter, DelimSpan};
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
expect_fragment,
- parser::{MetaVarKind, Op, RepeatKind, Separator},
+ parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator},
ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
};
@@ -769,23 +769,28 @@ fn match_meta_var(
it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
});
}
- MetaVarKind::Expr => {
- // `expr` should not match underscores, let expressions, or inline const. The latter
- // two are for [backwards compatibility][0].
+ MetaVarKind::Expr(expr) => {
+ // `expr_2021` should not match underscores, let expressions, or inline const.
+ // The latter two are for [backwards compatibility][0].
+ // And `expr` also should not contain let expressions but may contain the other two
+ // since `Edition2024`.
// HACK: Macro expansion should not be done using "rollback and try another alternative".
// rustc [explicitly checks the next token][1].
// [0]: https://github.com/rust-lang/rust/issues/86730
// [1]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
match input.peek_n(0) {
- Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it)))
- if it.sym == sym::underscore
- || it.sym == sym::let_
- || it.sym == sym::const_ =>
- {
- return ExpandResult::only_err(ExpandError::new(
- it.span,
- ExpandErrorKind::NoMatchingRule,
- ))
+ Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) => {
+ let is_err = if matches!(expr, ExprKind::Expr2021) {
+ it.sym == sym::underscore || it.sym == sym::let_ || it.sym == sym::const_
+ } else {
+ it.sym == sym::let_
+ };
+ if is_err {
+ return ExpandResult::only_err(ExpandError::new(
+ it.span,
+ ExpandErrorKind::NoMatchingRule,
+ ));
+ }
}
_ => {}
};
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs
index 286bd748cb..0084411535 100644
--- a/crates/mbe/src/expander/transcriber.rs
+++ b/crates/mbe/src/expander/transcriber.rs
@@ -97,7 +97,7 @@ impl Bindings {
| MetaVarKind::Ty
| MetaVarKind::Pat
| MetaVarKind::PatParam
- | MetaVarKind::Expr
+ | MetaVarKind::Expr(_)
| MetaVarKind::Ident => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
sym: sym::missing.clone(),
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index 218c04640f..2efe318f61 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -106,6 +106,16 @@ pub(crate) enum RepeatKind {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(crate) enum ExprKind {
+ // Matches expressions using the post-edition 2024. Was written using
+ // `expr` in edition 2024 or later.
+ Expr,
+ // Matches expressions using the pre-edition 2024 rules.
+ // Either written using `expr` in edition 2021 or earlier or.was written using `expr_2021`.
+ Expr2021,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum MetaVarKind {
Path,
Ty,
@@ -116,7 +126,7 @@ pub(crate) enum MetaVarKind {
Meta,
Item,
Vis,
- Expr,
+ Expr(ExprKind),
Ident,
Tt,
Lifetime,
@@ -277,17 +287,27 @@ fn eat_fragment_kind(
let kind = match ident.sym.as_str() {
"path" => MetaVarKind::Path,
"ty" => MetaVarKind::Ty,
- "pat" => match edition(ident.span.ctx) {
- Edition::Edition2015 | Edition::Edition2018 => MetaVarKind::PatParam,
- Edition::Edition2021 | Edition::Edition2024 => MetaVarKind::Pat,
- },
+ "pat" => {
+ if edition(ident.span.ctx).at_least_2021() {
+ MetaVarKind::Pat
+ } else {
+ MetaVarKind::PatParam
+ }
+ }
"pat_param" => MetaVarKind::PatParam,
"stmt" => MetaVarKind::Stmt,
"block" => MetaVarKind::Block,
"meta" => MetaVarKind::Meta,
"item" => MetaVarKind::Item,
"vis" => MetaVarKind::Vis,
- "expr" => MetaVarKind::Expr,
+ "expr" => {
+ if edition(ident.span.ctx).at_least_2024() {
+ MetaVarKind::Expr(ExprKind::Expr)
+ } else {
+ MetaVarKind::Expr(ExprKind::Expr2021)
+ }
+ }
+ "expr_2021" => MetaVarKind::Expr(ExprKind::Expr2021),
"ident" => MetaVarKind::Ident,
"tt" => MetaVarKind::Tt,
"lifetime" => MetaVarKind::Lifetime,
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index 5422c9ae64..f6f12a9f9a 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -177,3 +177,149 @@ fn main() {
}"#]],
);
}
+
+#[test]
+fn expr_2021() {
+ check(
+ Edition::Edition2024,
+ Edition::Edition2024,
+ r#"
+($($e:expr),* $(,)?) => {
+ $($e);* ;
+};
+"#,
+ r#"
+ _,
+ const { 1 },
+"#,
+ expect![[r#"
+ IDENT _ 1:[email protected]#0
+ PUNCH ; [joint] 0:[email protected]#0
+ IDENT const 1:[email protected]#0
+ LITERAL Integer 1 1:[email protected]#0
+ PUNCH ; [alone] 0:[email protected]#0
+
+ _;
+ (const {
+ 1
+ });"#]],
+ );
+ check(
+ Edition::Edition2021,
+ Edition::Edition2024,
+ r#"
+($($e:expr),* $(,)?) => {
+ $($e);* ;
+};
+"#,
+ r#"
+ _,
+"#,
+ expect![[r#"
+ ExpandError {
+ inner: (
+ NoMatchingRule,
+ ),
+ }
+
+ PUNCH ; [alone] 0:[email protected]#0
+
+ ;"#]],
+ );
+ check(
+ Edition::Edition2021,
+ Edition::Edition2024,
+ r#"
+($($e:expr),* $(,)?) => {
+ $($e);* ;
+};
+"#,
+ r#"
+ const { 1 },
+"#,
+ expect![[r#"
+ ExpandError {
+ inner: (
+ NoMatchingRule,
+ ),
+ }
+
+ PUNCH ; [alone] 0:[email protected]#0
+
+ ;"#]],
+ );
+ check(
+ Edition::Edition2024,
+ Edition::Edition2024,
+ r#"
+($($e:expr_2021),* $(,)?) => {
+ $($e);* ;
+};
+"#,
+ r#"
+ 4,
+ "literal",
+ funcall(),
+ future.await,
+ break 'foo bar,
+"#,
+ expect![[r#"
+ LITERAL Integer 4 1:[email protected]#0
+ PUNCH ; [joint] 0:[email protected]#0
+ LITERAL Str literal 1:[email protected]#0
+ PUNCH ; [joint] 0:[email protected]#0
+ IDENT funcall 1:[email protected]#0
+ PUNCH ; [joint] 0:[email protected]#0
+ IDENT future 1:[email protected]#0
+ PUNCH . [alone] 1:[email protected]#0
+ IDENT await 1:[email protected]#0
+ PUNCH ; [joint] 0:[email protected]#0
+ IDENT break 1:[email protected]#0
+ PUNCH ' [joint] 1:[email protected]#0
+ IDENT foo 1:[email protected]#0
+ IDENT bar 1:[email protected]#0
+ PUNCH ; [alone] 0:[email protected]#0
+
+ 4;
+ "literal";
+ (funcall());
+ (future.await);
+ (break 'foo bar);"#]],
+ );
+ check(
+ Edition::Edition2024,
+ Edition::Edition2024,
+ r#"
+($($e:expr_2021),* $(,)?) => {
+ $($e);* ;
+};
+"#,
+ r#"
+ _,
+"#,
+ expect![[r#"
+ ExpandError {
+ inner: (
+ NoMatchingRule,
+ ),
+ }
+
+ PUNCH ; [alone] 0:[email protected]#0
+
+ ;"#]],
+ );
+}