about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShoyu Vanilla <modulo641@gmail.com>2024-09-18 15:58:03 +0900
committerShoyu Vanilla <modulo641@gmail.com>2024-09-18 15:58:03 +0900
commit65e87e2c7f89b70461a3818593c553cf88a99bc3 (patch)
treec1664d4693fcbbf25bbfb47d854ac241a1d57643
parentb9be0f2cb6024d5e4e65943d551ed5c5aa7dbd89 (diff)
downloadrust-65e87e2c7f89b70461a3818593c553cf88a99bc3.tar.gz
rust-65e87e2c7f89b70461a3818593c553cf88a99bc3.zip
feat: Implement `expr_2021`
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs31
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs32
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/tests.rs146
5 files changed, 192 insertions, 21 deletions
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index 43604eb232d..f8c1d027c60 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index e69d7d14e25..90f56cc31da 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index 286bd748cbe..00844115355 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index 218c04640f1..2efe318f614 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
index 5422c9ae644..f6f12a9f9a0 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs
+++ b/src/tools/rust-analyzer/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#"
+            SUBTREE $$ 1:0@0..25#0 1:0@0..25#0
+              IDENT   _ 1:0@5..6#0
+              PUNCH   ; [joint] 0:0@36..37#0
+              SUBTREE () 0:0@34..35#0 0:0@34..35#0
+                IDENT   const 1:0@12..17#0
+                SUBTREE {} 1:0@18..19#0 1:0@22..23#0
+                  LITERAL Integer 1 1:0@20..21#0
+              PUNCH   ; [alone] 0:0@39..40#0
+
+            _;
+            (const  {
+                1
+            });"#]],
+    );
+    check(
+        Edition::Edition2021,
+        Edition::Edition2024,
+        r#"
+($($e:expr),* $(,)?) => {
+    $($e);* ;
+};
+"#,
+        r#"
+    _,
+"#,
+        expect![[r#"
+            ExpandError {
+                inner: (
+                    1:0@5..6#0,
+                    NoMatchingRule,
+                ),
+            }
+
+            SUBTREE $$ 1:0@0..8#0 1:0@0..8#0
+              PUNCH   ; [alone] 0:0@39..40#0
+
+            ;"#]],
+    );
+    check(
+        Edition::Edition2021,
+        Edition::Edition2024,
+        r#"
+($($e:expr),* $(,)?) => {
+    $($e);* ;
+};
+"#,
+        r#"
+    const { 1 },
+"#,
+        expect![[r#"
+            ExpandError {
+                inner: (
+                    1:0@5..10#0,
+                    NoMatchingRule,
+                ),
+            }
+
+            SUBTREE $$ 1:0@0..18#0 1:0@0..18#0
+              PUNCH   ; [alone] 0:0@39..40#0
+
+            ;"#]],
+    );
+    check(
+        Edition::Edition2024,
+        Edition::Edition2024,
+        r#"
+($($e:expr_2021),* $(,)?) => {
+    $($e);* ;
+};
+"#,
+        r#"
+    4,
+    "literal",
+    funcall(),
+    future.await,
+    break 'foo bar,
+"#,
+        expect![[r#"
+            SUBTREE $$ 1:0@0..76#0 1:0@0..76#0
+              LITERAL Integer 4 1:0@5..6#0
+              PUNCH   ; [joint] 0:0@41..42#0
+              LITERAL Str literal 1:0@12..21#0
+              PUNCH   ; [joint] 0:0@41..42#0
+              SUBTREE () 0:0@39..40#0 0:0@39..40#0
+                IDENT   funcall 1:0@27..34#0
+                SUBTREE () 1:0@34..35#0 1:0@35..36#0
+              PUNCH   ; [joint] 0:0@41..42#0
+              SUBTREE () 0:0@39..40#0 0:0@39..40#0
+                IDENT   future 1:0@42..48#0
+                PUNCH   . [alone] 1:0@48..49#0
+                IDENT   await 1:0@49..54#0
+              PUNCH   ; [joint] 0:0@41..42#0
+              SUBTREE () 0:0@39..40#0 0:0@39..40#0
+                IDENT   break 1:0@60..65#0
+                PUNCH   ' [joint] 1:0@66..67#0
+                IDENT   foo 1:0@67..70#0
+                IDENT   bar 1:0@71..74#0
+              PUNCH   ; [alone] 0:0@44..45#0
+
+            4;
+            "literal";
+            (funcall());
+            (future.await);
+            (break 'foo bar);"#]],
+    );
+    check(
+        Edition::Edition2024,
+        Edition::Edition2024,
+        r#"
+($($e:expr_2021),* $(,)?) => {
+    $($e);* ;
+};
+"#,
+        r#"
+    _,
+"#,
+        expect![[r#"
+            ExpandError {
+                inner: (
+                    1:0@5..6#0,
+                    NoMatchingRule,
+                ),
+            }
+
+            SUBTREE $$ 1:0@0..8#0 1:0@0..8#0
+              PUNCH   ; [alone] 0:0@44..45#0
+
+            ;"#]],
+    );
+}