about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/matching.rs49
-rw-r--r--crates/mbe/src/expander/matcher.rs12
2 files changed, 57 insertions, 4 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
index fc90c6e9f37..26f16542cbb 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
@@ -136,3 +136,52 @@ macro_rules! m { ($($i:ident)? $vis:vis) => () }
 "#]],
     )
 }
+
+// For this test and the one below, see rust-lang/rust#86730.
+#[test]
+fn expr_dont_match_let_expr() {
+    check(
+        r#"
+macro_rules! foo {
+    ($e:expr) => { $e }
+}
+
+fn test() {
+    foo!(let a = 3);
+}
+"#,
+        expect![[r#"
+macro_rules! foo {
+    ($e:expr) => { $e }
+}
+
+fn test() {
+    /* error: no rule matches input tokens */missing;
+}
+"#]],
+    );
+}
+
+#[test]
+fn expr_dont_match_inline_const() {
+    check(
+        r#"
+macro_rules! foo {
+    ($e:expr) => { $e }
+}
+
+fn test() {
+    foo!(const { 3 });
+}
+"#,
+        expect![[r#"
+macro_rules! foo {
+    ($e:expr) => { $e }
+}
+
+fn test() {
+    /* error: no rule matches input tokens */missing;
+}
+"#]],
+    );
+}
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 3f656df25f7..b6c5c1026ee 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -698,12 +698,16 @@ fn match_meta_var(kind: MetaVarKind, input: &mut TtIter<'_>) -> ExpandResult<Opt
         MetaVarKind::Item => parser::PrefixEntryPoint::Item,
         MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
         MetaVarKind::Expr => {
-            // `expr` should not match underscores.
+            // `expr` should not match underscores, let expressions, or inline const. The latter
+            // two are for [backwards compatibility][0].
             // HACK: Macro expansion should not be done using "rollback and try another alternative".
-            // rustc [explicitly checks the next token][0].
-            // [0]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
+            // 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.text == "_" => {
+                Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it)))
+                    if it.text == "_" || it.text == "let" || it.text == "const" =>
+                {
                     return ExpandResult::only_err(ExpandError::NoMatchingRule)
                 }
                 _ => {}