Rollup merge of #120221 - compiler-errors:statements-are-not-patterns, r=nnethercote
Don't make statement nonterminals match pattern nonterminals
Right now, the heuristic we use to check if a token may begin a pattern nonterminal falls back to `may_be_ident`:
ef71f1047e/compiler/rustc_parse/src/parser/nonterminal.rs (L21-L37)
This has the unfortunate side effect that a `stmt` nonterminal eagerly matches against a `pat` nonterminal, leading to a parse error:
```rust
macro_rules! m {
($pat:pat) => {};
($stmt:stmt) => {};
}
macro_rules! m2 {
($stmt:stmt) => {
m! { $stmt }
};
}
m2! { let x = 1 }
```
This PR fixes it by more accurately reflecting the set of nonterminals that may begin a pattern nonterminal.
As a side-effect, I modified `Token::can_begin_pattern` to work correctly and used that in `Parser::nonterminal_may_begin_with`.
This commit is contained in:
commit
1fd0c71818
5 changed files with 65 additions and 42 deletions
|
@ -86,25 +86,7 @@ impl<'a> Parser<'a> {
|
|||
token::Interpolated(nt) => may_be_ident(nt),
|
||||
_ => false,
|
||||
},
|
||||
NonterminalKind::Pat(pat_kind) => match &token.kind {
|
||||
// box, ref, mut, and other identifiers (can stricten)
|
||||
token::Ident(..) | token::NtIdent(..) |
|
||||
token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern
|
||||
token::OpenDelim(Delimiter::Bracket) | // slice pattern
|
||||
token::BinOp(token::And) | // reference
|
||||
token::BinOp(token::Minus) | // negative literal
|
||||
token::AndAnd | // double reference
|
||||
token::Literal(_) | // literal
|
||||
token::DotDot | // range pattern (future compat)
|
||||
token::DotDotDot | // range pattern (future compat)
|
||||
token::PathSep | // path
|
||||
token::Lt | // path (UFCS constant)
|
||||
token::BinOp(token::Shl) => true, // path (double UFCS)
|
||||
// leading vert `|` or-pattern
|
||||
token::BinOp(token::Or) => matches!(pat_kind, PatWithOr),
|
||||
token::Interpolated(nt) => may_be_ident(nt),
|
||||
_ => false,
|
||||
},
|
||||
NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind),
|
||||
NonterminalKind::Lifetime => match &token.kind {
|
||||
token::Lifetime(_) | token::NtLifetime(..) => true,
|
||||
_ => false,
|
||||
|
|
|
@ -444,7 +444,11 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let mut lo = self.token.span;
|
||||
|
||||
if self.token.is_keyword(kw::Let) && self.look_ahead(1, |tok| tok.can_begin_pattern()) {
|
||||
if self.token.is_keyword(kw::Let)
|
||||
&& self.look_ahead(1, |tok| {
|
||||
tok.can_begin_pattern(token::NtPatKind::PatParam { inferred: false })
|
||||
})
|
||||
{
|
||||
self.bump();
|
||||
self.dcx().emit_err(RemoveLet { span: lo });
|
||||
lo = self.token.span;
|
||||
|
|
|
@ -378,7 +378,10 @@ impl<'a> Parser<'a> {
|
|||
if self.may_recover()
|
||||
&& prev_token_before_parsing == token::PathSep
|
||||
&& (style == PathStyle::Expr && self.token.can_begin_expr()
|
||||
|| style == PathStyle::Pat && self.token.can_begin_pattern())
|
||||
|| style == PathStyle::Pat
|
||||
&& self.token.can_begin_pattern(token::NtPatKind::PatParam {
|
||||
inferred: false,
|
||||
}))
|
||||
{
|
||||
snapshot = Some(self.create_snapshot_for_diagnostic());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue