1
Fork 0

Rework pattern and expression nonterminal kinds.

Merge `PatParam`/`PatWithOr`, and `Expr`/`Expr2021`, for a few reasons.

- It's conceptually nice, because the two pattern kinds and the two
  expression kinds are very similar.

- With expressions in particular, there are several places where both
  expression kinds get the same treatment.

- It removes one unreachable match arm.

- Most importantly, for #124141 I will need to introduce a new type
  `MetaVarKind` that is very similar to `NonterminalKind`, but records a
  couple of extra fields for expression metavars. It's nicer to have a
  single `MetaVarKind::Expr` expression variant to hold those extra
  fields instead of duplicating them across two variants
  `MetaVarKind::{Expr,Expr2021}`. And then it makes sense for patterns
  to be treated the same way, and for `NonterminalKind` to also be
  treated the same way.

I also clarified the comments, because I have long found them a little
hard to understand.
This commit is contained in:
Nicholas Nethercote 2024-06-23 08:13:56 +10:00
parent 70fa67c0b2
commit e2aa38e6ab
5 changed files with 71 additions and 60 deletions

View file

@ -10,7 +10,9 @@ use crate::mbe::transcribe::transcribe;
use ast::token::IdentIsRaw;
use rustc_ast as ast;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*};
use rustc_ast::token::{
self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*,
};
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{NodeId, DUMMY_NODE_ID};
use rustc_ast_pretty::pprust;
@ -1145,7 +1147,7 @@ fn check_matcher_core<'tt>(
// Macros defined in the current crate have a real node id,
// whereas macros from an external crate have a dummy id.
if def.id != DUMMY_NODE_ID
&& matches!(kind, NonterminalKind::PatParam { inferred: true })
&& matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
&& matches!(
next_token,
TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)
@ -1155,7 +1157,7 @@ fn check_matcher_core<'tt>(
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
span,
name,
Some(NonterminalKind::PatParam { inferred: false }),
Some(NonterminalKind::Pat(PatParam { inferred: false })),
));
sess.psess.buffer_lint(
RUST_2021_INCOMPATIBLE_OR_PATTERNS,
@ -1188,14 +1190,14 @@ fn check_matcher_core<'tt>(
);
err.span_label(sp, format!("not allowed after `{kind}` fragments"));
if kind == NonterminalKind::PatWithOr
if kind == NonterminalKind::Pat(PatWithOr)
&& sess.psess.edition.at_least_rust_2021()
&& next_token.is_token(&BinOp(token::BinOpToken::Or))
{
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
span,
name,
Some(NonterminalKind::PatParam { inferred: false }),
Some(NonterminalKind::Pat(PatParam { inferred: false })),
));
err.span_suggestion(
span,
@ -1295,9 +1297,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
// maintain
IsInFollow::Yes
}
NonterminalKind::Stmt
| NonterminalKind::Expr
| NonterminalKind::Expr2021 { inferred: _ } => {
NonterminalKind::Stmt | NonterminalKind::Expr(_) => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
match tok {
TokenTree::Token(token) => match token.kind {
@ -1307,7 +1307,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
_ => IsInFollow::No(TOKENS),
}
}
NonterminalKind::PatParam { .. } => {
NonterminalKind::Pat(PatParam { .. }) => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
match tok {
TokenTree::Token(token) => match token.kind {
@ -1320,7 +1320,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
_ => IsInFollow::No(TOKENS),
}
}
NonterminalKind::PatWithOr => {
NonterminalKind::Pat(PatWithOr) => {
const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
match tok {
TokenTree::Token(token) => match token.kind {

View file

@ -2,7 +2,7 @@ use crate::errors;
use crate::mbe::macro_parser::count_metavar_decls;
use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token};
use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token};
use rustc_ast::{tokenstream, NodeId};
use rustc_ast_pretty::pprust;
use rustc_feature::Features;
@ -109,7 +109,7 @@ pub(super) fn parse(
});
NonterminalKind::Ident
});
if kind == (NonterminalKind::Expr2021 { inferred: false })
if kind == NonterminalKind::Expr(Expr2021 { inferred: false })
&& !features.expr_fragment_specifier_2024
{
rustc_session::parse::feature_err(