Skip to content

Commit

Permalink
Auto merge of #13800 - lowr:fix/mbe-expr-backwards-compat, r=Veykril
Browse files Browse the repository at this point in the history
fix: don't let mbe expr fragments match let exprs and inline consts

Fixes #11729

`expr` fragment in mbe should not match let expressions and inline consts for backwards compatibility. See rust-lang/rust#86730 for details.

This patch is porting [this logic in rustc](https://github.com/rust-lang/rust/blob/f0c4da49983aa699f715caf681e3154b445fb60b/compiler/rustc_parse/src/parser/nonterminal.rs#L28-L34) (which is called [here in rustc's mbe engine](https://github.com/rust-lang/rust/blob/f0c4da49983aa699f715caf681e3154b445fb60b/compiler/rustc_expand/src/mbe/macro_parser.rs#L576)) to our mbe engine.
  • Loading branch information
bors committed Dec 20, 2022
2 parents ffedfc6 + e027ac0 commit ccbf8fe
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 4 deletions.
49 changes: 49 additions & 0 deletions crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
"#]],
);
}
12 changes: 8 additions & 4 deletions crates/mbe/src/expander/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
_ => {}
Expand Down

0 comments on commit ccbf8fe

Please sign in to comment.