Open
Description
I tried this code:
macro_rules! let_let_oof {
($p:pat) => {
let_let_oof! { let let $p }
};
(let let $p:pat) => {
fn a() {
let $p = 5;
}
}
}
let_let_oof! { x }
I expected the code to compile and the macro to expand as follows:
fn a() {
let x = 5;
}
Instead, compilation failed:
error: expected pattern, found `let`
--> bad-code2.rs:3:24
|
3 | let_let_oof! { let let $p }
| ^^^ help: remove the unnecessary `let` keyword
...
12 | let_let_oof! { x }
| ------------------ in this macro invocation
|
= note: this error originates in the macro `let_let_oof` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected identifier, found keyword `let`
--> bad-code2.rs:3:28
|
3 | let_let_oof! { let let $p }
| ^^^ expected identifier, found keyword
...
12 | let_let_oof! { x }
| ------------------ in this macro invocation
|
= note: this error originates in the macro `let_let_oof` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
Meta
rustc --version --verbose
:
rustc 1.70.0-nightly (8a73f50d8 2023-03-11)
binary: rustc
commit-hash: 8a73f50d875840b8077b8ec080fa41881d7ce40d
commit-date: 2023-03-11
host: x86_64-unknown-linux-gnu
release: 1.70.0-nightly
LLVM version: 15.0.7
Occurs on latest stable and nightly.
Additional context
I believe there are two issues here:
- (error 2) The parser consumes
let
as an identifier and then fails because it is not a valid identifier;Parser::can_be_ident_pat
(seecompiler/rustc_parse/parser/pat.rs:811
) returns true on keywords and then the caller (compiler/rustc_parse/parser/pat.rs:398
) attempts to parse an ident pattern and promptly fails because it sees a keyword. - (error 1) On top of this (and thus no code has been broken), a regression occurred with the introduction of the following code (see
compiler/rustc_parse/parser/pat.rs:345
) which eagerly consumes tokens without being behind aParser::may_recover
gate (this is similar to Breaking change in macro_rules ty fragment parsing in version 1.68 #107796, that regression I caused, right? cc @compiler-errors):
if self.token.is_keyword(kw::Let) && self.look_ahead(1, |tok| tok.can_begin_pattern()) {
self.bump();
self.sess.emit_err(RemoveLet { span: lo });
lo = self.token.span;
}
If this is correct, I'd like to PR it please :).