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 fc90c6e9f370..26f16542cbb2 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 3f656df25f7d..b6c5c1026ee0 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 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) } _ => {}