Prepare for invisible delimiters.

Current places where `Interpolated` is used are going to change to
instead use invisible delimiters. This prepares for that.
- It adds invisible delimiter cases to the `can_begin_*`/`may_be_*`
  methods and the `failed_to_match_macro` that are equivalent to the
  existing `Interpolated` cases.
- It adds panics/asserts in some places where invisible delimiters
  should never occur.
- In `Parser::parse_struct_fields` it excludes an ident + invisible
  delimiter from special consideration in an error message, because
  that's quite different to an ident + paren/brace/bracket.
This commit is contained in:
Nicholas Nethercote 2024-04-17 09:37:00 +10:00
parent cfafa9380b
commit cee88f7a3f
5 changed files with 108 additions and 14 deletions

View file

@ -3,7 +3,9 @@ use rustc_ast::ptr::P;
use rustc_ast::token::Nonterminal::*;
use rustc_ast::token::NtExprKind::*;
use rustc_ast::token::NtPatKind::*;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
use rustc_ast::token::{
self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_errors::PResult;
@ -22,7 +24,28 @@ impl<'a> Parser<'a> {
#[inline]
pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
/// Checks whether the non-terminal may contain a single (non-keyword) identifier.
fn may_be_ident(nt: &token::Nonterminal) -> bool {
fn may_be_ident(kind: MetaVarKind) -> bool {
match kind {
MetaVarKind::Stmt
| MetaVarKind::Pat(_)
| MetaVarKind::Expr { .. }
| MetaVarKind::Ty
| MetaVarKind::Literal // `true`, `false`
| MetaVarKind::Meta
| MetaVarKind::Path => true,
MetaVarKind::Item
| MetaVarKind::Block
| MetaVarKind::Vis => false,
MetaVarKind::Ident
| MetaVarKind::Lifetime
| MetaVarKind::TT => unreachable!(),
}
}
/// Old variant of `may_be_ident`. Being phased out.
fn nt_may_be_ident(nt: &Nonterminal) -> bool {
match nt {
NtStmt(_)
| NtPat(_)
@ -69,7 +92,8 @@ impl<'a> Parser<'a> {
| token::Ident(..)
| token::NtIdent(..)
| token::NtLifetime(..)
| token::Interpolated(_) => true,
| token::Interpolated(_)
| token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true,
_ => token.can_begin_type(),
},
NonterminalKind::Block => match &token.kind {
@ -79,11 +103,29 @@ impl<'a> Parser<'a> {
NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false,
},
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
MetaVarKind::Block
| MetaVarKind::Stmt
| MetaVarKind::Expr { .. }
| MetaVarKind::Literal => true,
MetaVarKind::Item
| MetaVarKind::Pat(_)
| MetaVarKind::Ty
| MetaVarKind::Meta
| MetaVarKind::Path
| MetaVarKind::Vis => false,
MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => {
unreachable!()
}
},
_ => false,
},
NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
token::PathSep | token::Ident(..) | token::NtIdent(..) => true,
token::Interpolated(nt) => may_be_ident(nt),
token::Interpolated(nt) => nt_may_be_ident(nt),
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => {
may_be_ident(*kind)
}
_ => false,
},
NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind),