Auto merge of #137517 - nnethercote:rm-NtPat-NtItem-NtStmt, r=petrochenkov

Remove `NtPat`, `NtMeta`, and `NtPath`

Another part of #124141.

r? `@petrochenkov`
This commit is contained in:
bors 2025-02-28 21:32:39 +00:00
commit aa3c2d73ef
35 changed files with 189 additions and 236 deletions

View file

@ -1024,7 +1024,7 @@ pub(crate) struct SuffixedLiteralInAttribute {
pub(crate) struct InvalidMetaItem {
#[primary_span]
pub span: Span,
pub token: Token,
pub descr: String,
#[subdiagnostic]
pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
}

View file

@ -1,4 +1,6 @@
use rustc_ast::{self as ast, Attribute, attr, token};
use rustc_ast as ast;
use rustc_ast::token::{self, MetaVarKind};
use rustc_ast::{Attribute, attr};
use rustc_errors::codes::*;
use rustc_errors::{Diag, PResult};
use rustc_span::{BytePos, Span};
@ -9,7 +11,7 @@ use super::{
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle, Trailing,
UsePreAttrPos,
};
use crate::{errors, exp, fluent_generated as fluent, maybe_whole};
use crate::{errors, exp, fluent_generated as fluent};
// Public for rustfmt usage
#[derive(Debug)]
@ -269,7 +271,12 @@ impl<'a> Parser<'a> {
/// PATH `=` UNSUFFIXED_LIT
/// The delimiters or `=` are still put into the resulting token stream.
pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> {
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
if let Some(item) = self.eat_metavar_seq_with_matcher(
|mv_kind| matches!(mv_kind, MetaVarKind::Meta { .. }),
|this| this.parse_attr_item(force_collect),
) {
return Ok(item);
}
// Attr items don't have attributes.
self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| {
@ -396,18 +403,17 @@ impl<'a> Parser<'a> {
&mut self,
unsafe_allowed: AllowLeadingUnsafe,
) -> PResult<'a, ast::MetaItem> {
// We can't use `maybe_whole` here because it would bump in the `None`
// case, which we don't want.
if let token::Interpolated(nt) = &self.token.kind
&& let token::NtMeta(attr_item) = &**nt
{
match attr_item.meta(attr_item.path.span) {
Some(meta) => {
self.bump();
return Ok(meta);
}
None => self.unexpected()?,
}
if let Some(MetaVarKind::Meta { has_meta_form }) = self.token.is_metavar_seq() {
return if has_meta_form {
let attr_item = self
.eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
this.parse_attr_item(ForceCollect::No)
})
.unwrap();
Ok(attr_item.meta(attr_item.path.span).unwrap())
} else {
self.unexpected_any()
};
}
let lo = self.token.span;
@ -464,7 +470,7 @@ impl<'a> Parser<'a> {
let mut err = errors::InvalidMetaItem {
span: self.token.span,
token: self.token.clone(),
descr: super::token_descr(&self.token),
quote_ident_sugg: None,
};

View file

@ -1,17 +1,15 @@
use std::mem::take;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use ast::token::IdentIsRaw;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
use rustc_ast::tokenstream::AttrTokenTree;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::{
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, HasTokens, Item, ItemKind, Param, Pat,
PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
Path, PathSegment, QSelf, Recovered, Ty, TyKind,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
@ -2406,52 +2404,6 @@ impl<'a> Parser<'a> {
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
err.span_label(span, "expected expression");
// Walk the chain of macro expansions for the current token to point at how the original
// code was interpreted. This helps the user realize when a macro argument of one type is
// later reinterpreted as a different type, like `$x:expr` being reinterpreted as `$x:pat`
// in a subsequent macro invocation (#71039).
let mut tok = self.token.clone();
let mut labels = vec![];
while let TokenKind::Interpolated(nt) = &tok.kind {
let tokens = nt.tokens();
labels.push(Arc::clone(nt));
if let Some(tokens) = tokens
&& let tokens = tokens.to_attr_token_stream()
&& let tokens = tokens.0.deref()
&& let [AttrTokenTree::Token(token, _)] = &tokens[..]
{
tok = token.clone();
} else {
break;
}
}
let mut iter = labels.into_iter().peekable();
let mut show_link = false;
while let Some(nt) = iter.next() {
let descr = nt.descr();
if let Some(next) = iter.peek() {
let next_descr = next.descr();
if next_descr != descr {
err.span_label(next.use_span(), format!("this is expected to be {next_descr}"));
err.span_label(
nt.use_span(),
format!(
"this is interpreted as {}, but it is expected to be {}",
next_descr, descr,
),
);
show_link = true;
}
}
}
if show_link {
err.note(
"when forwarding a matched fragment to another macro-by-example, matchers in the \
second macro will see an opaque AST of the fragment type, not the underlying \
tokens",
);
}
err
}

View file

@ -4,7 +4,7 @@ use core::mem;
use core::ops::{Bound, ControlFlow};
use ast::mut_visit::{self, MutVisitor};
use ast::token::IdentIsRaw;
use ast::token::{IdentIsRaw, MetaVarKind};
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@ -1344,6 +1344,7 @@ impl<'a> Parser<'a> {
fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
let span = self.token.span;
if let token::Interpolated(nt) = &self.token.kind {
match &**nt {
token::NtExpr(e) | token::NtLiteral(e) => {
@ -1351,11 +1352,6 @@ impl<'a> Parser<'a> {
self.bump();
return Ok(e);
}
token::NtPath(path) => {
let path = (**path).clone();
self.bump();
return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path)));
}
token::NtBlock(block) => {
let block = block.clone();
self.bump();
@ -1363,6 +1359,10 @@ impl<'a> Parser<'a> {
}
_ => {}
};
} else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| {
this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))
}) {
return Ok(self.mk_expr(span, ExprKind::Path(None, path)));
}
// Outer attributes are already parsed and will be

View file

@ -4,7 +4,7 @@ use std::mem;
use ast::token::IdentIsRaw;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::util::case::Case;
use rustc_ast::{self as ast};
@ -3071,8 +3071,10 @@ impl<'a> Parser<'a> {
fn is_named_param(&self) -> bool {
let offset = match &self.token.kind {
token::Interpolated(nt) => match &**nt {
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
token::OpenDelim(Delimiter::Invisible(origin)) => match origin {
InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => {
return self.check_noexpect_past_close_delim(&token::Colon);
}
_ => 0,
},
token::BinOp(token::And) | token::AndAnd => 1,

View file

@ -24,7 +24,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use path::PathStyle;
use rustc_ast::ptr::P;
use rustc_ast::token::{
self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind,
self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtPatKind, Token,
TokenKind,
};
use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree};
use rustc_ast::util::case::Case;
@ -1745,7 +1746,10 @@ pub enum ParseNtResult {
Tt(TokenTree),
Ident(Ident, IdentIsRaw),
Lifetime(Ident, IdentIsRaw),
Pat(P<ast::Pat>, NtPatKind),
Ty(P<ast::Ty>),
Meta(P<ast::AttrItem>),
Path(P<ast::Path>),
Vis(P<ast::Visibility>),
/// This variant will eventually be removed, along with `Token::Interpolate`.

View file

@ -32,7 +32,7 @@ impl<'a> Parser<'a> {
| MetaVarKind::Expr { .. }
| MetaVarKind::Ty { .. }
| MetaVarKind::Literal // `true`, `false`
| MetaVarKind::Meta
| MetaVarKind::Meta { .. }
| MetaVarKind::Path => true,
MetaVarKind::Item
@ -49,11 +49,9 @@ impl<'a> Parser<'a> {
fn nt_may_be_ident(nt: &Nonterminal) -> bool {
match nt {
NtStmt(_)
| NtPat(_)
| NtExpr(_)
| NtLiteral(_) // `true`, `false`
| NtMeta(_)
| NtPath(_) => true,
=> true,
NtItem(_) | NtBlock(_) => false,
}
@ -99,7 +97,7 @@ impl<'a> Parser<'a> {
token::NtLifetime(..) => true,
token::Interpolated(nt) => match &**nt {
NtBlock(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
NtItem(_) | NtPat(_) | NtMeta(_) | NtPath(_) => false,
NtItem(_) => false,
},
token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k {
MetaVarKind::Block
@ -109,7 +107,7 @@ impl<'a> Parser<'a> {
MetaVarKind::Item
| MetaVarKind::Pat(_)
| MetaVarKind::Ty { .. }
| MetaVarKind::Meta
| MetaVarKind::Meta { .. }
| MetaVarKind::Path
| MetaVarKind::Vis => false,
MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => {
@ -170,15 +168,18 @@ impl<'a> Parser<'a> {
}
},
NonterminalKind::Pat(pat_kind) => {
NtPat(self.collect_tokens_no_attrs(|this| match pat_kind {
PatParam { .. } => this.parse_pat_no_top_alt(None, None),
PatWithOr => this.parse_pat_no_top_guard(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
),
})?)
return Ok(ParseNtResult::Pat(
self.collect_tokens_no_attrs(|this| match pat_kind {
PatParam { .. } => this.parse_pat_no_top_alt(None, None),
PatWithOr => this.parse_pat_no_top_guard(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
),
})?,
pat_kind,
));
}
NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?),
NonterminalKind::Literal => {
@ -203,9 +204,13 @@ impl<'a> Parser<'a> {
};
}
NonterminalKind::Path => {
NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
return Ok(ParseNtResult::Path(P(
self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?
)));
}
NonterminalKind::Meta => {
return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?)));
}
NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(ForceCollect::Yes)?)),
NonterminalKind::Vis => {
return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| {
this.parse_visibility(FollowedByType::Yes)

View file

@ -2,7 +2,8 @@ use std::ops::Bound;
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
use rustc_ast::token::NtPatKind::*;
use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, MetaVarKind, Token};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{
@ -30,7 +31,7 @@ use crate::errors::{
UnexpectedVertVertInPattern, WrapInParens,
};
use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
#[derive(PartialEq, Copy, Clone)]
pub enum Expected {
@ -689,6 +690,27 @@ impl<'a> Parser<'a> {
PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt);
}
fn eat_metavar_pat(&mut self) -> Option<P<Pat>> {
// Must try both kinds of pattern nonterminals.
if let Some(pat) = self.eat_metavar_seq_with_matcher(
|mv_kind| matches!(mv_kind, MetaVarKind::Pat(PatParam { .. })),
|this| this.parse_pat_no_top_alt(None, None),
) {
Some(pat)
} else if let Some(pat) = self.eat_metavar_seq(MetaVarKind::Pat(PatWithOr), |this| {
this.parse_pat_no_top_guard(
None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
)
}) {
Some(pat)
} else {
None
}
}
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
/// allowed).
fn parse_pat_with_range_pat(
@ -698,7 +720,10 @@ impl<'a> Parser<'a> {
syntax_loc: Option<PatternLocation>,
) -> PResult<'a, P<Pat>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole!(self, NtPat, |pat| pat);
if let Some(pat) = self.eat_metavar_pat() {
return Ok(pat);
}
let mut lo = self.token.span;
@ -1043,10 +1068,8 @@ impl<'a> Parser<'a> {
self.recover_additional_muts();
// Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
if let token::Interpolated(nt) = &self.token.kind {
if let token::NtPat(..) = &**nt {
self.expected_ident_found_err().emit();
}
if let Some(MetaVarKind::Pat(_)) = self.token.is_metavar_seq() {
self.expected_ident_found_err().emit();
}
// Parse the pattern we hope to be an identifier.

View file

@ -15,9 +15,9 @@ use tracing::debug;
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType};
use crate::errors::{PathSingleColon, PathTripleColon};
use crate::errors::{self, PathSingleColon, PathTripleColon};
use crate::exp;
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
use crate::{errors, exp, maybe_whole};
/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
@ -194,7 +194,11 @@ impl<'a> Parser<'a> {
}
};
maybe_whole!(self, NtPath, |path| reject_generics_if_mod_style(self, path.into_inner()));
if let Some(path) =
self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type))
{
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.