1
Fork 0

Auto merge of #133436 - nnethercote:rm-NtVis-NtTy, r=petrochenkov

Remove `NtVis` and `NtTy`

The next part of #124141. The first actual remove of `Nonterminal` variants. `NtVis` is a simple case that doesn't get much use, but `NtTy` is more complex.

r? `@petrochenkov`
This commit is contained in:
bors 2025-02-22 06:09:14 +00:00
commit b6d3be4948
20 changed files with 229 additions and 76 deletions

View file

@ -117,12 +117,15 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
($self: expr, $allow_qpath_recovery: expr) => {
if $allow_qpath_recovery
&& $self.may_recover()
&& $self.look_ahead(1, |t| t == &token::PathSep)
&& let token::Interpolated(nt) = &$self.token.kind
&& let token::NtTy(ty) = &**nt
&& let Some(mv_kind) = $self.token.is_metavar_seq()
&& let token::MetaVarKind::Ty { .. } = mv_kind
&& $self.check_noexpect_past_close_delim(&token::PathSep)
{
let ty = ty.clone();
$self.bump();
// Reparse the type, then move to recovery.
let ty = $self
.eat_metavar_seq(mv_kind, |this| this.parse_ty_no_question_mark_recover())
.expect("metavar seq ty");
return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
}
};
@ -614,6 +617,24 @@ impl<'a> Parser<'a> {
self.token == *tok
}
// Check the first token after the delimiter that closes the current
// delimited sequence. (Panics if used in the outermost token stream, which
// has no delimiters.) It uses a clone of the relevant tree cursor to skip
// past the entire `TokenTree::Delimited` in a single step, avoiding the
// need for unbounded token lookahead.
//
// Primarily used when `self.token` matches
// `OpenDelim(Delimiter::Invisible(_))`, to look ahead through the current
// metavar expansion.
fn check_noexpect_past_close_delim(&self, tok: &TokenKind) -> bool {
let mut tree_cursor = self.token_cursor.stack.last().unwrap().clone();
tree_cursor.bump();
matches!(
tree_cursor.curr(),
Some(TokenTree::Token(token::Token { kind, .. }, _)) if kind == tok
)
}
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
///
/// the main purpose of this function is to reduce the cluttering of the suggestions list
@ -721,6 +742,43 @@ impl<'a> Parser<'a> {
if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) }
}
/// Consume a sequence produced by a metavar expansion, if present.
fn eat_metavar_seq<T>(
&mut self,
mv_kind: MetaVarKind,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> Option<T> {
self.eat_metavar_seq_with_matcher(|mvk| mvk == mv_kind, f)
}
/// A slightly more general form of `eat_metavar_seq`, for use with the
/// `MetaVarKind` variants that have parameters, where an exact match isn't
/// desired.
fn eat_metavar_seq_with_matcher<T>(
&mut self,
match_mv_kind: impl Fn(MetaVarKind) -> bool,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> Option<T> {
if let token::OpenDelim(delim) = self.token.kind
&& let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
&& match_mv_kind(mv_kind)
{
self.bump();
let res = f(self).expect("failed to reparse {mv_kind:?}");
if let token::CloseDelim(delim) = self.token.kind
&& let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim
&& match_mv_kind(mv_kind)
{
self.bump();
Some(res)
} else {
panic!("no close delim when reparsing {mv_kind:?}");
}
} else {
None
}
}
/// Is the given keyword `kw` followed by a non-reserved identifier?
fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool {
self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
@ -1455,7 +1513,11 @@ impl<'a> Parser<'a> {
/// so emit a proper diagnostic.
// Public for rustfmt usage.
pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
maybe_whole!(self, NtVis, |vis| vis.into_inner());
if let Some(vis) = self
.eat_metavar_seq(MetaVarKind::Vis, |this| this.parse_visibility(FollowedByType::Yes))
{
return Ok(vis);
}
if !self.eat_keyword(exp!(Pub)) {
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
@ -1683,7 +1745,9 @@ pub enum ParseNtResult {
Tt(TokenTree),
Ident(Ident, IdentIsRaw),
Lifetime(Ident, IdentIsRaw),
Ty(P<ast::Ty>),
Vis(P<ast::Visibility>),
/// This case will eventually be removed, along with `Token::Interpolate`.
/// This variant will eventually be removed, along with `Token::Interpolate`.
Nt(Arc<Nonterminal>),
}

View file

@ -30,7 +30,7 @@ impl<'a> Parser<'a> {
MetaVarKind::Stmt
| MetaVarKind::Pat(_)
| MetaVarKind::Expr { .. }
| MetaVarKind::Ty
| MetaVarKind::Ty { .. }
| MetaVarKind::Literal // `true`, `false`
| MetaVarKind::Meta
| MetaVarKind::Path => true,
@ -51,14 +51,11 @@ impl<'a> Parser<'a> {
NtStmt(_)
| NtPat(_)
| NtExpr(_)
| NtTy(_)
| NtLiteral(_) // `true`, `false`
| NtMeta(_)
| NtPath(_) => true,
NtItem(_)
| NtBlock(_)
| NtVis(_) => false,
NtItem(_) | NtBlock(_) => false,
}
}
@ -88,7 +85,7 @@ impl<'a> Parser<'a> {
NonterminalKind::Ident => get_macro_ident(token).is_some(),
NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
NonterminalKind::Vis => match token.kind {
// The follow-set of :vis + "priv" keyword + interpolated
// The follow-set of :vis + "priv" keyword + interpolated/metavar-expansion.
token::Comma
| token::Ident(..)
| token::NtIdent(..)
@ -102,7 +99,7 @@ impl<'a> Parser<'a> {
token::NtLifetime(..) => true,
token::Interpolated(nt) => match &**nt {
NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false,
NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false,
},
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
MetaVarKind::Block
@ -111,7 +108,7 @@ impl<'a> Parser<'a> {
| MetaVarKind::Literal => true,
MetaVarKind::Item
| MetaVarKind::Pat(_)
| MetaVarKind::Ty
| MetaVarKind::Ty { .. }
| MetaVarKind::Meta
| MetaVarKind::Path
| MetaVarKind::Vis => false,
@ -189,7 +186,9 @@ impl<'a> Parser<'a> {
NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
}
NonterminalKind::Ty => {
NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
return Ok(ParseNtResult::Ty(
self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
));
}
// this could be handled like a token, since it is one
NonterminalKind::Ident => {
@ -208,8 +207,9 @@ impl<'a> Parser<'a> {
}
NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)),
NonterminalKind::Vis => {
NtVis(P(self
.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))
return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| {
this.parse_visibility(FollowedByType::Yes)
})?)));
}
NonterminalKind::Lifetime => {
// We want to keep `'keyword` parsing, just like `keyword` is still

View file

@ -2,7 +2,7 @@ use std::mem;
use ast::token::IdentIsRaw;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::token::{self, Delimiter, MetaVarKind, Token, TokenKind};
use rustc_ast::{
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
@ -196,14 +196,12 @@ impl<'a> Parser<'a> {
maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
if let token::Interpolated(nt) = &self.token.kind {
if let token::NtTy(ty) = &**nt {
if let ast::TyKind::Path(None, path) = &ty.kind {
let path = path.clone();
self.bump();
return Ok(reject_generics_if_mod_style(self, path));
}
}
// If we have a `ty` metavar in the form of a path, reparse it directly as a path, instead
// of reparsing it as a `ty` and then extracting the path.
if let Some(path) = self.eat_metavar_seq(MetaVarKind::Ty { is_path: true }, |this| {
this.parse_path(PathStyle::Type)
}) {
return Ok(reject_generics_if_mod_style(self, path));
}
let lo = self.token.span;

View file

@ -1,5 +1,5 @@
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
@ -18,7 +18,7 @@ use crate::errors::{
HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
NestedCVariadicType, ReturnTypesUseThinArrow,
};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
/// Signals whether parsing a type should allow `+`.
///
@ -183,7 +183,8 @@ impl<'a> Parser<'a> {
)
}
/// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
/// Parse a type without recovering `:` as `->` to avoid breaking code such
/// as `where fn() : for<'a>`.
pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
self.parse_ty_common(
AllowPlus::Yes,
@ -247,7 +248,13 @@ impl<'a> Parser<'a> {
) -> PResult<'a, P<Ty>> {
let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
maybe_whole!(self, NtTy, |ty| ty);
if let Some(ty) = self.eat_metavar_seq_with_matcher(
|mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
|this| this.parse_ty_no_question_mark_recover(),
) {
return Ok(ty);
}
let lo = self.token.span;
let mut impl_dyn_multi = false;