From c74572682eda9c204f7815a9e09dadf3f5db0bdf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 13 Jun 2024 09:03:02 +1000 Subject: [PATCH] XXX: finalizing --- compiler/rustc_ast/src/attr/mod.rs | 4 +- compiler/rustc_ast/src/token.rs | 213 +++++++++++------- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_expand/src/base.rs | 27 ++- compiler/rustc_expand/src/mbe/macro_rules.rs | 25 +- compiler/rustc_expand/src/mbe/quoted.rs | 55 ++--- compiler/rustc_expand/src/mbe/transcribe.rs | 53 +++-- compiler/rustc_parse/src/parser/attr.rs | 27 +-- compiler/rustc_parse/src/parser/expr.rs | 117 +++++----- compiler/rustc_parse/src/parser/item.rs | 24 +- compiler/rustc_parse/src/parser/mod.rs | 125 +++++----- .../rustc_parse/src/parser/nonterminal.rs | 64 +++--- compiler/rustc_parse/src/parser/pat.rs | 53 +++-- compiler/rustc_parse/src/parser/path.rs | 28 +-- compiler/rustc_parse/src/parser/stmt.rs | 75 +++--- compiler/rustc_parse/src/parser/ty.rs | 17 +- src/tools/rustfmt/src/parse/macros/mod.rs | 6 +- 17 files changed, 472 insertions(+), 443 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index ff9dd054dcc72..a57f51d0b1232 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -7,7 +7,7 @@ use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; use crate::ast::{Path, PathSegment, DUMMY_NODE_ID}; use crate::ptr::P; -use crate::token::{self, CommentKind, Delimiter, InvisibleOrigin, NonterminalKind, Token}; +use crate::token::{self, CommentKind, Delimiter, InvisibleOrigin, MetaVarKind, Token}; use crate::tokenstream::{DelimSpan, Spacing, TokenTree}; use crate::tokenstream::{LazyAttrTokenStream, TokenStream}; use crate::util::comments; @@ -368,7 +368,7 @@ impl MetaItem { _span, _spacing, Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Meta | NonterminalKind::Path, + MetaVarKind::Meta | MetaVarKind::Path, )), _stream, )) => { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 7f7e90df09a25..a6698799ac42c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1,5 +1,7 @@ pub use BinOpToken::*; pub use LitKind::*; +pub use NtExprKind::*; +pub use NtPatKind::*; pub use TokenKind::*; use crate::ast; @@ -38,7 +40,7 @@ pub enum BinOpToken { #[derive(Copy, Clone, Debug, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum InvisibleOrigin { // From the expansion of a metavariable in a declarative macro. - MetaVar(NonterminalKind), + MetaVar(MetaVarKind), // Converted from `proc_macro::Delimiter` in // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. @@ -49,6 +51,54 @@ pub enum InvisibleOrigin { FlattenToken, } +/// Annoyingly similar to `NonterminalKind`, but the slightly differences are important. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] +pub enum MetaVarKind { + Item, + Block, + Stmt, + Pat(NtPatKind), + Expr { + kind: NtExprKind, + // This field is needed for `Token::can_begin_literal_maybe_minus`. + can_begin_literal_maybe_minus: bool, + // This field is needed for `Token::can_begin_string_literal`. + can_begin_string_literal: bool, + }, + Ty, + Ident, + Lifetime, + Literal, + Meta, + Path, + Vis, + TT, +} + +impl fmt::Display for MetaVarKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use MetaVarKind::*; + let sym = match self { + Item => sym::item, + Block => sym::block, + Stmt => sym::stmt, + Pat(PatParam { inferred: true } | PatWithOr) => sym::pat, + Pat(PatParam { inferred: false }) => sym::pat_param, + Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr, + Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021, + Ty => sym::ty, + Ident => sym::ident, + Lifetime => sym::lifetime, + Literal => sym::literal, + Meta => sym::meta, + Path => sym::path, + Vis => sym::vis, + TT => sym::tt, + }; + write!(f, "{}", sym) + } +} + /// Describes how a sequence of token trees is delimited. /// Cannot use `proc_macro::Delimiter` directly because this /// structure should implement some additional traits. @@ -136,7 +186,7 @@ impl Lit { match token.uninterpolate().kind { Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), Literal(token_lit) => Some(token_lit), - OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(NonterminalKind::Literal))) => { + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(MetaVarKind::Literal))) => { panic!("njn: FROM_TOKEN (1)"); // if let NtExpr(expr) | NtLiteral(expr) = &**nt // && let ast::ExprKind::Lit(token_lit) = expr.kind => @@ -144,7 +194,9 @@ impl Lit { // Some(token_lit) // } } - OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(NonterminalKind::Expr))) => { + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(MetaVarKind::Expr { + .. + }))) => { panic!("njn: FROM_TOKEN (2)"); // if let NtExpr(expr) | NtLiteral(expr) = &**nt // && let ast::ExprKind::Lit(token_lit) = expr.kind => @@ -509,11 +561,10 @@ impl Token { Lifetime(..) | // labeled loop Pound => true, // expression attributes OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Block | - NonterminalKind::Expr | - NonterminalKind::Expr2021 { .. } | - NonterminalKind::Literal | - NonterminalKind::Path + MetaVarKind::Block | + MetaVarKind::Expr { .. } | + MetaVarKind::Literal | + MetaVarKind::Path ))) => true, _ => false, } @@ -536,11 +587,10 @@ impl Token { | Lt | BinOp(Shl) // associated path | PathSep => true, // global path OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Block | - NonterminalKind::PatParam { .. } | - NonterminalKind::PatWithOr | - NonterminalKind::Path | - NonterminalKind::Literal + MetaVarKind::Block | + MetaVarKind::Pat(_) | + MetaVarKind::Path | + MetaVarKind::Literal ))) => true, _ => false, } @@ -562,8 +612,8 @@ impl Token { Lt | BinOp(Shl) | // associated path PathSep => true, // global path OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Ty | - NonterminalKind::Path + MetaVarKind::Ty | + MetaVarKind::Path ))) => true, // For anonymous structs or unions, which only appear in specific positions // (type of struct fields or union fields), we don't consider them as regular types @@ -577,10 +627,7 @@ impl Token { OpenDelim(Delimiter::Brace) | Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Expr - | NonterminalKind::Expr2021 { .. } - | NonterminalKind::Block - | NonterminalKind::Literal, + MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, _ => false, } @@ -628,22 +675,13 @@ impl Token { match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - // njn: fix up - // Interpolated(ref nt) => match &**nt { - // NtLiteral(_) => true, - // NtExpr(e) => match &e.kind { - // ast::ExprKind::Lit(_) => true, - // ast::ExprKind::Unary(ast::UnOp::Neg, e) => { - // matches!(&e.kind, ast::ExprKind::Lit(_)) - // } - // _ => false, - // }, - // _ => false, - // }, - // njn: too simple compared to what's above? - OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Literal | NonterminalKind::Expr | NonterminalKind::Expr2021 { .. }, - ))) => true, + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { + MetaVarKind::Literal => true, + MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { + can_begin_literal_maybe_minus + } + _ => false, + }, _ => false, } } @@ -651,19 +689,11 @@ impl Token { pub fn can_begin_string_literal(&self) -> bool { match self.uninterpolate().kind { Literal(..) => true, - // njn: fix up - // Interpolated(ref nt) => match &**nt { - // NtLiteral(_) => true, - // NtExpr(e) => match &e.kind { - // ast::ExprKind::Lit(_) => true, - // _ => false, - // }, - // _ => false, - // }, - // njn: too simple compared to what's above? - OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Literal | NonterminalKind::Expr | NonterminalKind::Expr2021, - ))) => true, + OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind))) => match mv_kind { + MetaVarKind::Literal => true, + MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal, + _ => false, + }, _ => false, } } @@ -718,24 +748,24 @@ impl Token { self.ident().is_some_and(|(ident, _)| ident.name == name) } - /// Would `maybe_reparse_metavar_expr` in `parser.rs` return `Ok(..)`? + /// Would `eat_metavar_expr` in `parser.rs` return `Ok(..)`? /// That is, is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_metavar_expr(&self) -> bool { matches!( self.is_metavar_seq(), Some( - NonterminalKind::Expr - | NonterminalKind::Literal - | NonterminalKind::Path - | NonterminalKind::Block + MetaVarKind::Expr { .. } + | MetaVarKind::Literal + | MetaVarKind::Path + | MetaVarKind::Block ) ) } /// Are we at a block from a metavar (`$b:block`)? pub fn is_metavar_block(&self) -> bool { - matches!(self.is_metavar_seq(), Some(NonterminalKind::Block)) + matches!(self.is_metavar_seq(), Some(MetaVarKind::Block)) } /// Returns `true` if the token is either the `mut` or `const` keyword. @@ -750,7 +780,7 @@ impl Token { pub fn is_path_start(&self) -> bool { self == &PathSep || self.is_qpath_start() - || matches!(self.is_metavar_seq(), Some(NonterminalKind::Path)) + || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) || self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident() } @@ -822,7 +852,7 @@ impl Token { /// Is this an invisible open delimiter at the start of a token sequence /// from an expanded metavar? - pub fn is_metavar_seq(&self) -> Option { + pub fn is_metavar_seq(&self) -> Option { match self.kind { OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => Some(kind), _ => None, @@ -898,24 +928,34 @@ impl PartialEq for Token { } } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] +pub enum NtPatKind { + // Matches or-patterns. Was written using `pat` in edition 2021 or later. + PatWithOr, + // Doesn't match or-patterns. + // - `inferred`: was written using `pat` in edition 2015 or 2018. + // - `!inferred`: was written using `pat_param`. + PatParam { inferred: bool }, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] +pub enum NtExprKind { + // Matches expressions using the post-edition 2024. Was written using + // `expr` in edition 2024 or later. + Expr, + // Matches expressions using the pre-edition 2024 rules. + // - `inferred`: was written using `expr` in edition 2021 or earlier. + // - `!inferred`: was written using `expr_2021`. + Expr2021 { inferred: bool }, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NonterminalKind { Item, Block, Stmt, - PatParam { - /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the - /// edition of the span. This is used for diagnostics. - inferred: bool, - }, - PatWithOr, - Expr, - /// Matches an expression using the rules from edition 2021 and earlier. - Expr2021 { - /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the - /// edition of the span. This is used for diagnostics AND feature gating. - inferred: bool, - }, + Pat(NtPatKind), + Expr(NtExprKind), Ty, Ident, Lifetime, @@ -937,20 +977,22 @@ impl NonterminalKind { sym::item => NonterminalKind::Item, sym::block => NonterminalKind::Block, sym::stmt => NonterminalKind::Stmt, - sym::pat => match edition() { - Edition::Edition2015 | Edition::Edition2018 => { - NonterminalKind::PatParam { inferred: true } + sym::pat => { + if edition().at_least_rust_2021() { + NonterminalKind::Pat(PatWithOr) + } else { + NonterminalKind::Pat(PatParam { inferred: true }) } - Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, - }, - sym::pat_param => NonterminalKind::PatParam { inferred: false }, - sym::expr => match edition() { - Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => { - NonterminalKind::Expr2021 { inferred: true } + } + sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }), + sym::expr => { + if edition().at_least_rust_2024() { + NonterminalKind::Expr(Expr) + } else { + NonterminalKind::Expr(Expr2021 { inferred: true }) } - Edition::Edition2024 => NonterminalKind::Expr, - }, - sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false }, + } + sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }), sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -962,15 +1004,16 @@ impl NonterminalKind { _ => return None, }) } + fn symbol(self) -> Symbol { match self { NonterminalKind::Item => sym::item, NonterminalKind::Block => sym::block, NonterminalKind::Stmt => sym::stmt, - NonterminalKind::PatParam { inferred: false } => sym::pat_param, - NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, - NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr, - NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021, + NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat, + NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param, + NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr, + NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 03aff6f96330e..154ce59330f01 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -169,7 +169,7 @@ impl CfgEval<'_, '_> { }, Annotatable::Stmt(_) => |parser| { Ok(Annotatable::Stmt(P(parser - .parse_stmt_without_recovery(false, ForceCollect::Yes)? + .parse_stmt_without_recovery(false, ForceCollect::Yes, false)? .unwrap()))) }, Annotatable::Expr(_) => { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 6d1df778ca1af..9ec7776583f80 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -5,7 +5,7 @@ use crate::module::DirOwnership; use rustc_ast::attr::MarkedAttrs; use rustc_ast::ptr::P; -use rustc_ast::token::NonterminalKind; +use rustc_ast::token::MetaVarKind; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind}; @@ -15,7 +15,7 @@ use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools}; -use rustc_parse::parser::{ParseNtResult, Parser}; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::MACRO_ARGUMENTS; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::{parse::ParseSess, Limit, Session}; @@ -1425,24 +1425,27 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, psess: & } pub(crate) fn stream_pretty_printing_compatibility_hack( - kind: NonterminalKind, + kind: MetaVarKind, stream: &TokenStream, psess: &ParseSess, ) { let item = match kind { - NonterminalKind::Item => { + MetaVarKind::Item => { let mut parser = Parser::new(psess, stream.clone(), None); - let Ok(ParseNtResult::Item(item)) = parser.parse_nonterminal(kind) else { - panic!("failed to reparse"); - }; - item + // No need to collect tokens for this simple check. + parser + .parse_item(ForceCollect::No) + .expect("failed to reparse item") + .expect("an actual item") } - NonterminalKind::Stmt => { + MetaVarKind::Stmt => { // njn: reparsing and then checking for StmtKind::Item sucks, hmm let mut parser = Parser::new(psess, stream.clone(), None); - let Ok(ParseNtResult::Stmt(stmt)) = parser.parse_nonterminal(kind) else { - panic!("failed to reparse"); - }; + // No need to collect tokens for this simple check. + let stmt = parser + .parse_stmt(ForceCollect::No) + .expect("failed to reparse") + .expect("an actual stmt"); match &stmt.kind { ast::StmtKind::Item(item) => item.clone(), _ => return, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index fd790731514df..dc55f4578c0a6 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -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,14 +1147,17 @@ 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!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)) + && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true })) + && matches!( + next_token, + TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or) + ) { // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param. 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, @@ -1185,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, @@ -1292,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 { @@ -1304,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 { @@ -1317,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 { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index fb4d69fccb8d2..6e1f90bdf90fa 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -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, 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; @@ -85,36 +85,31 @@ pub(super) fn parse( span.edition() } }; - let kind = - token::NonterminalKind::from_symbol(fragment.name, edition) - .unwrap_or_else(|| { - let help = match fragment.name { - sym::expr_2021 => { - format!( - "fragment specifier `expr_2021` \ - requires Rust 2021 or later\n\ - {VALID_FRAGMENT_NAMES_MSG}" - ) - } - _ if edition().at_least_rust_2021() - && features - .expr_fragment_specifier_2024 => - { - VALID_FRAGMENT_NAMES_MSG_2021.into() - } - _ => VALID_FRAGMENT_NAMES_MSG.into(), - }; - sess.dcx().emit_err( - errors::InvalidFragmentSpecifier { - span, - fragment, - help, - }, - ); - token::NonterminalKind::Ident + let kind = NonterminalKind::from_symbol(fragment.name, edition) + .unwrap_or_else(|| { + let help = match fragment.name { + sym::expr_2021 => { + format!( + "fragment specifier `expr_2021` \ + requires Rust 2021 or later\n\ + {VALID_FRAGMENT_NAMES_MSG}" + ) + } + _ if edition().at_least_rust_2021() + && features.expr_fragment_specifier_2024 => + { + VALID_FRAGMENT_NAMES_MSG_2021.into() + } + _ => VALID_FRAGMENT_NAMES_MSG.into(), + }; + sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + span, + fragment, + help, }); - if kind - == (token::NonterminalKind::Expr2021 { inferred: false }) + NonterminalKind::Ident + }); + if kind == NonterminalKind::Expr(Expr2021 { inferred: false }) && !features.expr_fragment_specifier_2024 { rustc_session::parse::feature_err( diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index d5f5aa5e91926..29b4d1ac58f26 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -7,9 +7,10 @@ use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR}; use crate::mbe::{self, KleeneOp, MetaVarExpr}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::IdentIsRaw; -use rustc_ast::token::{self, Delimiter, InvisibleOrigin, NonterminalKind, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::StmtKind; +use rustc_ast::{ExprKind, UnOp}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, Diag, DiagCtxtHandle, PResult}; use rustc_parse::parser::ParseNtResult; @@ -268,7 +269,7 @@ pub(super) fn transcribe<'a>( // some of the unnecessary whitespace. let ident = MacroRulesNormalizedIdent::new(original_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { - let mut mk_delimited = |nt_kind, stream| { + let mut mk_delimited = |mv_kind, stream| { // Emit as a token stream within `Delimiter::Invisible` to maintain parsing // priorities. marker.visit_span(&mut sp); @@ -277,7 +278,7 @@ pub(super) fn transcribe<'a>( TokenTree::Delimited( DelimSpan::from_single(sp), DelimSpacing::new(Spacing::Alone, Spacing::Alone), - Delimiter::Invisible(InvisibleOrigin::MetaVar(nt_kind)), + Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)), stream, ) }; @@ -300,10 +301,10 @@ pub(super) fn transcribe<'a>( TokenTree::token_alone(kind, sp) } MatchedSingle(ParseNtResult::Item(ref item)) => { - mk_delimited(NonterminalKind::Item, TokenStream::from_ast(item)) + mk_delimited(MetaVarKind::Item, TokenStream::from_ast(item)) } MatchedSingle(ParseNtResult::Block(ref block)) => { - mk_delimited(NonterminalKind::Block, TokenStream::from_ast(block)) + mk_delimited(MetaVarKind::Block, TokenStream::from_ast(block)) } MatchedSingle(ParseNtResult::Stmt(ref stmt)) => { let stream = if let StmtKind::Empty = stmt.kind { @@ -312,32 +313,46 @@ pub(super) fn transcribe<'a>( } else { TokenStream::from_ast(stmt) }; - mk_delimited(NonterminalKind::Stmt, stream) + mk_delimited(MetaVarKind::Stmt, stream) } - MatchedSingle(ParseNtResult::PatParam(ref pat, inferred)) => mk_delimited( - NonterminalKind::PatParam { inferred: *inferred }, - TokenStream::from_ast(pat), - ), - MatchedSingle(ParseNtResult::PatWithOr(ref pat)) => { - mk_delimited(NonterminalKind::PatWithOr, TokenStream::from_ast(pat)) + MatchedSingle(ParseNtResult::Pat(ref pat, pat_kind)) => { + mk_delimited(MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat)) } - MatchedSingle(ParseNtResult::Expr(ref expr)) => { - mk_delimited(NonterminalKind::Expr, TokenStream::from_ast(expr)) + MatchedSingle(ParseNtResult::Expr(ref expr, kind)) => { + // njn: rename these? is_literal? is_negative_literal? + let (can_begin_literal_maybe_minus, can_begin_string_literal) = + match &expr.kind { + ExprKind::Lit(_) => (true, true), + ExprKind::Unary(UnOp::Neg, e) + if matches!(&e.kind, ExprKind::Lit(_)) => + { + (true, false) + } + _ => (false, false), + }; + mk_delimited( + MetaVarKind::Expr { + kind: *kind, + can_begin_literal_maybe_minus, + can_begin_string_literal, + }, + TokenStream::from_ast(expr), + ) } MatchedSingle(ParseNtResult::Literal(ref expr)) => { - mk_delimited(NonterminalKind::Literal, TokenStream::from_ast(expr)) + mk_delimited(MetaVarKind::Literal, TokenStream::from_ast(expr)) } MatchedSingle(ParseNtResult::Ty(ref ty)) => { - mk_delimited(NonterminalKind::Ty, TokenStream::from_ast(ty)) + mk_delimited(MetaVarKind::Ty, TokenStream::from_ast(ty)) } MatchedSingle(ParseNtResult::Meta(ref meta)) => { - mk_delimited(NonterminalKind::Meta, TokenStream::from_ast(meta)) + mk_delimited(MetaVarKind::Meta, TokenStream::from_ast(meta)) } MatchedSingle(ParseNtResult::Path(ref path)) => { - mk_delimited(NonterminalKind::Path, TokenStream::from_ast(path)) + mk_delimited(MetaVarKind::Path, TokenStream::from_ast(path)) } MatchedSingle(ParseNtResult::Vis(ref vis)) => { - mk_delimited(NonterminalKind::Vis, TokenStream::from_ast(vis)) + mk_delimited(MetaVarKind::Vis, TokenStream::from_ast(vis)) } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index efa558917d62d..53d46f7523f21 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,11 +1,10 @@ use crate::errors; use crate::fluent_generated as fluent; -use crate::maybe_reparse_metavar_seq; -use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, ParseNtResult, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; -use rustc_ast::token::{self, Delimiter, NonterminalKind}; +use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_errors::{codes::*, Diag, PResult}; use rustc_span::{sym, symbol::kw, BytePos, Span}; use thin_vec::ThinVec; @@ -249,14 +248,10 @@ 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, capture_tokens: bool) -> PResult<'a, ast::AttrItem> { - if let Some(item) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Meta, - NonterminalKind::Meta, - ParseNtResult::Meta(item), - item - ) { - return Ok(item.into_inner()); + if let Some(item) = + self.eat_metavar_seq(MetaVarKind::Meta, |this| this.parse_attr_item(true)) + { + return Ok(item); } let do_parse = |this: &mut Self| { @@ -384,13 +379,9 @@ impl<'a> Parser<'a> { pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { // Clone the parser so we can backtrack in the case where `attr_item.meta()` fails. let mut parser = self.clone(); - if let Some(attr_item) = maybe_reparse_metavar_seq!( - parser, - NonterminalKind::Meta, - NonterminalKind::Meta, - ParseNtResult::Meta(attr_item), - attr_item - ) { + if let Some(attr_item) = + parser.eat_metavar_seq(MetaVarKind::Meta, |this| this.parse_attr_item(true)) + { return match attr_item.meta(attr_item.path.span) { Some(meta) => { *self = parser; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 90ff9ddc2f5cc..eba24d57a531c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,8 +4,8 @@ use super::diagnostics::SnapshotParser; use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ - AttrWrapper, BlockMode, ClosureSpans, ForceCollect, ParseNtResult, Parser, PathStyle, - Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, TrailingToken, + AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, + SemiColonMode, SeqSep, TokenType, Trailing, TrailingToken, }; use crate::errors; @@ -16,7 +16,7 @@ use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSe use core::mem; use core::ops::ControlFlow; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, InvisibleOrigin, NonterminalKind, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::util::classify; use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; @@ -39,45 +39,40 @@ use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; use tracing::instrument; -/// Possibly reparse an expression produced from a metavar during declarative -/// macro expansion. -macro_rules! maybe_reparse_metavar_expr { - ($p:expr) => { - let span = $p.token.span; - if let Some(expr) = crate::maybe_reparse_metavar_seq!( - $p, - token::NonterminalKind::Expr, - token::NonterminalKind::Expr, - super::ParseNtResult::Expr(expr), - expr - ) { - return Ok(expr); - } else if let Some(lit) = crate::maybe_reparse_metavar_seq!( - $p, - token::NonterminalKind::Literal, - token::NonterminalKind::Literal, - super::ParseNtResult::Literal(lit), - lit - ) { - return Ok(lit); - } else if let Some(block) = crate::maybe_reparse_metavar_seq!( - $p, - token::NonterminalKind::Block, - token::NonterminalKind::Block, - super::ParseNtResult::Block(block), - block - ) { - return Ok($p.mk_expr(span, ExprKind::Block(block, None))); - } else if let Some(path) = crate::maybe_reparse_metavar_seq!( - $p, - token::NonterminalKind::Path, - token::NonterminalKind::Path, - super::ParseNtResult::Path(path), - path +impl<'a> Parser<'a> { + /// Possibly reparse an expression produced from a metavar during declarative + /// macro expansion. + fn eat_metavar_expr(&mut self) -> Option> { + let span = self.token.span; + if let Some(expr) = self.eat_metavar_seq_with_matcher( + |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), + |this| { + let expr = this.parse_expr_force_collect(); + // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly + // related to the FIXME in `collect_tokens_for_expr`. + if this.token.kind == token::Comma { + this.bump(); + } + expr + }, ) { - return Ok($p.mk_expr(span, ExprKind::Path(None, path.into_inner()))); + Some(expr) + } else if let Some(lit) = self.eat_metavar_seq(MetaVarKind::Literal, |this| { + this.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus()) + }) { + Some(lit) + } else if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| { + this.collect_tokens_no_attrs(|this| this.parse_block()) + }) { + Some(self.mk_expr(span, ExprKind::Block(block, None))) + } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { + this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) + }) { + Some(self.mk_expr(span, ExprKind::Path(None, path))) + } else { + None } - }; + } } #[derive(Debug)] @@ -1443,14 +1438,18 @@ impl<'a> Parser<'a> { /// correctly if called from `parse_dot_or_call_expr()`. fn parse_expr_bottom(&mut self) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); - maybe_reparse_metavar_expr!(self); + + if let Some(expr) = self.eat_metavar_expr() { + return Ok(expr); + } // Outer attributes are already parsed and will be // added to the return value after the fact. let restrictions = self.restrictions; self.with_res(restrictions - Restrictions::ALLOW_LET, |this| { - // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`. + // Note: when adding new syntax here, don't forget to adjust + // `TokenKind::can_begin_expr()`. let lo = this.token.span; if let token::Literal(_) = this.token.kind { // This match arm is a special-case of the `_` match arm below and @@ -2160,29 +2159,29 @@ impl<'a> Parser<'a> { Some(token_lit) } token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Literal, + MetaVarKind::Literal, ))) => { - let lit = crate::reparse_metavar_seq!( - self, - NonterminalKind::Literal, - ParseNtResult::Literal(lit), - lit - ); + let lit = self + .eat_metavar_seq(MetaVarKind::Literal, |this| { + // No need to collect tokens when we are only extracting `token_lit`. + this.parse_literal_maybe_minus() + }) + .expect("metavar seq literal"); let ast::ExprKind::Lit(token_lit) = lit.kind else { panic!("didn't reparse a literal"); }; Some(token_lit) } token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Expr, + mv_kind @ MetaVarKind::Expr { .. }, ))) => { let mut self2 = self.clone(); // njn: ugh - let expr = crate::reparse_metavar_seq!( - self2, - NonterminalKind::Expr, - ParseNtResult::Expr(expr), - expr - ); + let expr = self2 + .eat_metavar_seq(mv_kind, |this| { + // No need to collect tokens because we only consult `expr.kind`. + this.parse_expr_force_collect() + }) + .expect("metavar seq expr"); if let ast::ExprKind::Lit(token_lit) = expr.kind { *self = self2; Some(token_lit) @@ -2297,7 +2296,9 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - maybe_reparse_metavar_expr!(self); + if let Some(expr) = self.eat_metavar_expr() { + return Ok(expr); + } let lo = self.token.span; let minus_present = self.eat(&token::BinOp(token::Minus)); @@ -3164,7 +3165,7 @@ impl<'a> Parser<'a> { } self.restore_snapshot(pre_pat_snapshot); - match self.parse_stmt_without_recovery(true, ForceCollect::No) { + match self.parse_stmt_without_recovery(true, ForceCollect::No, false) { // Consume statements for as long as possible. Ok(Some(stmt)) => { stmts.push(stmt); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cadd423a3b08a..2906788625783 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,16 +1,15 @@ use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{ - AttrWrapper, FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle, Recovered, - Trailing, TrailingToken, + AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Recovered, Trailing, + TrailingToken, }; use crate::errors::{self, MacroExpandsToAdtField}; use crate::fluent_generated as fluent; -use crate::maybe_reparse_metavar_seq; use ast::token::IdentIsRaw; use rustc_ast::ast::*; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, InvisibleOrigin, NonterminalKind, 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}; @@ -124,13 +123,10 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { - if let Some(mut item) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Item, - NonterminalKind::Item, - ParseNtResult::Item(item), - item - ) { + if let Some(item) = + self.eat_metavar_seq(MetaVarKind::Item, |this| this.parse_item(ForceCollect::Yes)) + { + let mut item = item.expect("an actual item"); attrs.prepend_to_nt_inner(&mut item.attrs); return Ok(Some(item.into_inner())); } @@ -2907,9 +2903,9 @@ impl<'a> Parser<'a> { fn is_named_param(&self) -> bool { let offset = match &self.token.kind { token::OpenDelim(Delimiter::Invisible(origin)) => match origin { - InvisibleOrigin::MetaVar( - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr, - ) => return self.check_noexpect_past_close_delim(&token::Colon), + InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => { + return self.check_noexpect_past_close_delim(&token::Colon); + } _ => 0, }, token::BinOp(token::And) | token::AndAnd => 1, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index fc08ba2222f09..bed3a90894bdf 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -20,7 +20,8 @@ use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, NonterminalKind, Token, TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, + TokenKind, }; use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing}; use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; @@ -102,71 +103,22 @@ pub enum TrailingToken { MaybeComma, } -/// Reparses an invisible-delimited sequence produced by expansion of a -/// declarative macro metavariable. Will panic if called with a `self.token` -/// that is not an `InvisibleOrigin::Metavar` invisible open delimiter. -#[macro_export] -macro_rules! reparse_metavar_seq { - ($p:expr, $nt_kind:expr, $nt_res:pat, $ret:expr) => {{ - let delim = token::Delimiter::Invisible(token::InvisibleOrigin::MetaVar($nt_kind)); - $p.expect(&token::OpenDelim(delim)).expect("no open delim when reparsing"); - let Ok($nt_res) = $p.parse_nonterminal($nt_kind) else { - panic!("failed to reparse"); - }; - // njn: sometimes with expressions we get a trailing comma, possibly - // related to the FIXME in `collect_tokens_for_expr`. - if $nt_kind == NonterminalKind::Expr && matches!($p.token.kind, token::TokenKind::Comma) { - $p.bump(); - } - //$p.expect(&token::CloseDelim(delim)).expect("no close delim when reparsing"); - let res = $p.expect(&token::CloseDelim(delim)); - match res { - Ok(_) => {} - // njn: no close delim when reparsing: Token { kind: Comma, span: - // compiler/rustc_index/src/bit_set/tests.rs:305:10: 305:11 (#0) } - Err(_) => { - eprintln!("no close delim when reparsing: {:?}", $p.token); - $p.bump(); - panic!("no close delim when reparsing2: {:?}", $p.token); - } - } - $ret - }}; -} - -/// Reparses an an invisible-delimited sequence produced by expansion of a -/// declarative macro metavariable, if present. -/// -/// `$nt_kind_pat` and `$nt_kind` are always syntactically identical in -/// practice, but must be specified separately because one is a pattern and one -/// is an expression. Which is annoying but hard to avoid. -#[macro_export] -macro_rules! maybe_reparse_metavar_seq { - ($p:expr, $nt_kind_pat:pat, $nt_kind:expr, $nt_res:pat, $ret:expr) => { - if let Some($nt_kind_pat) = $p.token.is_metavar_seq() { - Some(crate::reparse_metavar_seq!($p, $nt_kind, $nt_res, $ret)) - } else { - None - } - }; -} - /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. #[macro_export] macro_rules! maybe_recover_from_interpolated_ty_qpath { ($self: expr, $allow_qpath_recovery: expr) => { if $allow_qpath_recovery && $self.may_recover() - && let Some(token::NonterminalKind::Ty) = $self.token.is_metavar_seq() + && let Some(token::MetaVarKind::Ty) = $self.token.is_metavar_seq() && $self.check_noexpect_past_close_delim(&token::PathSep) { // Reparse the type, then move to recovery. - let ty = crate::reparse_metavar_seq!( - $self, - token::NonterminalKind::Ty, - super::ParseNtResult::Ty(ty), - ty - ); + let ty = $self + .eat_metavar_seq(MetaVarKind::Ty, |this| { + this.collect_tokens_no_attrs(|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); } }; @@ -416,7 +368,7 @@ pub(super) enum TokenDescription { // pretty-printed. In error messages we must handle these specially // otherwise we get confusing things in messages like "expected `(`, found // ``". It's better to say e.g. "expected `(`, found type metavariable". - MetaVar(NonterminalKind), + MetaVar(MetaVarKind), } impl TokenDescription { @@ -719,6 +671,39 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } + /// Consume a sequence produced by a metavar expansion, if present. + fn eat_metavar_seq( + &mut self, + mv_kind: MetaVarKind, + f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + 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( + &mut self, + match_mv_kind: impl FnOnce(MetaVarKind) -> bool, + mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, + ) -> Option { + if let token::OpenDelim(delim) = self.token.kind + && let Delimiter::Invisible(token::InvisibleOrigin::MetaVar(mv_kind)) = delim + && match_mv_kind(mv_kind) + { + self.bump(); + let res = f(self).expect("failed to reparse {mv_kind:?}"); + if self.token.kind != token::CloseDelim(delim) { + panic!("no close delim when reparsing {mv_kind:?}"); + } + self.bump(); + Some(res) + } 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()) @@ -766,7 +751,7 @@ impl<'a> Parser<'a> { && self.look_ahead(dist + 1, |t| match &t.kind { token::OpenDelim(Delimiter::Brace) => true, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( - NonterminalKind::Block, + MetaVarKind::Block, ))) => true, _ => false, }) @@ -1022,8 +1007,9 @@ impl<'a> Parser<'a> { let initial_semicolon = self.token.span; while self.eat(&TokenKind::Semi) { - let _ = - self.parse_stmt_without_recovery(false, ForceCollect::Yes).unwrap_or_else(|e| { + let _ = self + .parse_stmt_without_recovery(false, ForceCollect::Yes, false) + .unwrap_or_else(|e| { e.cancel(); None }); @@ -1494,14 +1480,10 @@ impl<'a> Parser<'a> { /// so emit a proper diagnostic. // Public for rustfmt usage. pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> { - if let Some(vis) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Vis, - NonterminalKind::Vis, - ParseNtResult::Vis(vis), - vis - ) { - return Ok(vis.into_inner()); + if let Some(vis) = self.eat_metavar_seq(MetaVarKind::Vis, |this| { + this.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes)) + }) { + return Ok(vis); } if !self.eat_keyword(kw::Pub) { @@ -1747,9 +1729,8 @@ pub enum ParseNtResult { Item(P), Block(P), Stmt(P), - PatParam(P, /* inferred */ bool), - PatWithOr(P), - Expr(P), + Pat(P, NtPatKind), + Expr(P, NtExprKind), Literal(P), Ty(P), Meta(P), diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 7e86de23aaa3f..851ad3c4e599d 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,5 +1,8 @@ use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, InvisibleOrigin, NonterminalKind, Token}; +use rustc_ast::token::{ + self, Delimiter, InvisibleOrigin, MetaVarKind, NonterminalKind, NtExprKind::*, NtPatKind::*, + Token, +}; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; @@ -16,14 +19,12 @@ 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(kind: NonterminalKind) -> bool { - use NonterminalKind::*; + fn may_be_ident(kind: MetaVarKind) -> bool { + use MetaVarKind::*; match kind { Stmt - | PatParam { .. } - | PatWithOr - | Expr - | Expr2021 { .. } + | Pat(_) + | Expr { .. } | Ty | Literal // `true`, `false` | Meta @@ -40,14 +41,14 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 { inferred: _ } => { + NonterminalKind::Expr(Expr2021 { .. }) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } - NonterminalKind::Expr => { + NonterminalKind::Expr(Expr) => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -68,19 +69,17 @@ impl<'a> Parser<'a> { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { - NonterminalKind::Block - | NonterminalKind::Stmt - | NonterminalKind::Expr - | NonterminalKind::Expr2021 { .. } - | NonterminalKind::Literal => true, - NonterminalKind::Item - | NonterminalKind::PatParam { .. } - | NonterminalKind::PatWithOr - | NonterminalKind::Ty - | NonterminalKind::Meta - | NonterminalKind::Path - | NonterminalKind::Vis => false, - NonterminalKind::Lifetime | NonterminalKind::Ident | NonterminalKind::TT => { + 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!() } }, @@ -93,7 +92,7 @@ impl<'a> Parser<'a> { } _ => false, }, - NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind { + 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 @@ -108,7 +107,7 @@ impl<'a> Parser<'a> { token::Lt | // path (UFCS constant) token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern - token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr), + token::BinOp(token::Or) => matches!(pat_kind, PatWithOr), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { may_be_ident(*kind) } @@ -150,22 +149,23 @@ impl<'a> Parser<'a> { Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span))) } }, - NonterminalKind::PatParam { inferred } => Ok(ParseNtResult::PatParam( + NonterminalKind::Pat(pat_kind @ PatParam { .. }) => Ok(ParseNtResult::Pat( self.collect_tokens_no_attrs(|this| this.parse_pat_no_top_alt(None, None))?, - inferred, + pat_kind, )), - NonterminalKind::PatWithOr => { - Ok(ParseNtResult::PatWithOr(self.collect_tokens_no_attrs(|this| { + NonterminalKind::Pat(pat_kind @ PatWithOr) => Ok(ParseNtResult::Pat( + self.collect_tokens_no_attrs(|this| { this.parse_pat_allow_top_alt( None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe, ) - })?)) - } - NonterminalKind::Expr | NonterminalKind::Expr2021 { .. } => { - Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?)) + })?, + pat_kind, + )), + NonterminalKind::Expr(kind) => { + Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, kind)) } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 494e7ee0ecfaa..de06bd3bdd910 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,6 +1,4 @@ -use super::{ - ForceCollect, ParseNtResult, Parser, PathStyle, Restrictions, Trailing, TrailingToken, -}; +use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, TrailingToken}; use crate::errors::{ self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, @@ -12,11 +10,11 @@ use crate::errors::{ UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, }; +use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr}; -use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_reparse_metavar_seq}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, Delimiter, NonterminalKind, Token}; +use rustc_ast::token::{self, BinOpToken, Delimiter, MetaVarKind, NtPatKind::*, Token}; use rustc_ast::{ self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, @@ -427,6 +425,29 @@ impl<'a> Parser<'a> { None } + fn eat_metavar_pat(&mut self) -> Option> { + // 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.collect_tokens_no_attrs(|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.collect_tokens_no_attrs(|this| { + this.parse_pat_allow_top_alt( + 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( @@ -437,23 +458,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); - // Must try both kinds of pattern nonterminals. - if let Some(pat) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::PatParam { inferred }, - NonterminalKind::PatParam { inferred }, - ParseNtResult::PatParam(pat, _), - pat - ) { - return Ok(pat); - } - if let Some(pat) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::PatWithOr, - NonterminalKind::PatWithOr, - ParseNtResult::PatWithOr(pat), - pat - ) { + if let Some(pat) = self.eat_metavar_pat() { return Ok(pat); } @@ -776,9 +781,7 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. - if let Some(NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr) = - self.token.is_metavar_seq() - { + if let Some(MetaVarKind::Pat(_)) = self.token.is_metavar_seq() { self.expected_ident_found_err().emit(); } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index fd67501c04f27..7abc596435a76 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,11 +1,11 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; -use super::{ParseNtResult, Parser, Restrictions, TokenType}; +use super::{Parser, Restrictions, TokenType}; +use crate::errors; use crate::errors::PathSingleColon; use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma}; -use crate::{errors, maybe_reparse_metavar_seq}; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, NonterminalKind, 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, @@ -193,20 +193,20 @@ impl<'a> Parser<'a> { } }; - if let Some(path) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Path, - NonterminalKind::Path, - ParseNtResult::Path(path), - path - ) { - return Ok(reject_generics_if_mod_style(self, path.into_inner())); + if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { + this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) + }) { + return Ok(reject_generics_if_mod_style(self, path)); } - if let Some(NonterminalKind::Ty) = self.token.is_metavar_seq() { + if let Some(MetaVarKind::Ty) = self.token.is_metavar_seq() { let mut self2 = self.clone(); - let ty = - crate::reparse_metavar_seq!(self2, NonterminalKind::Ty, ParseNtResult::Ty(ty), ty); + let ty = self2 + .eat_metavar_seq(MetaVarKind::Ty, |this| { + // No need to collect tokens because we only consult `ty.kind`. + this.parse_ty_no_question_mark_recover() + }) + .expect("metavar seq ty"); if let ast::TyKind::Path(None, path) = ty.into_inner().kind { *self = self2; return Ok(reject_generics_if_mod_style(self, path)); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index b0b3c93323bb5..2efd418715be9 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -4,16 +4,15 @@ use super::expr::LhsExpr; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ - AttrWrapper, BlockMode, FnParseMode, ForceCollect, ParseNtResult, Parser, Restrictions, - SemiColonMode, TrailingToken, + AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, + TrailingToken, }; use crate::errors::{self, MalformedLoopLabel}; -use crate::maybe_reparse_metavar_seq; use ast::Label; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Delimiter, NonterminalKind, TokenKind}; +use rustc_ast::token::{self, Delimiter, MetaVarKind, TokenKind}; use rustc_ast::util::classify::{self, TrailingBrace}; use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle}; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt}; @@ -30,8 +29,8 @@ impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. // Public for rustfmt usage. - pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { - Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| { + pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { + Ok(self.parse_stmt_without_recovery(false, force_collect, false).unwrap_or_else(|e| { e.emit(); self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); None @@ -39,27 +38,25 @@ impl<'a> Parser<'a> { } /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of - /// whether or not we have attributes. - // Public for `cfg_eval` macro expansion. + /// whether or not we have attributes. If `force_full_expr` is true, parses the stmt without + /// using `Restriction::STMT_EXPR`. Public for `cfg_eval` macro expansion. pub fn parse_stmt_without_recovery( &mut self, capture_semi: bool, force_collect: ForceCollect, + force_full_expr: bool, ) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; - if let Some(mut stmt) = crate::maybe_reparse_metavar_seq!( - self, - NonterminalKind::Stmt, - NonterminalKind::Stmt, - ParseNtResult::Stmt(stmt), - stmt - ) { + if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| { + this.parse_stmt_without_recovery(false, ForceCollect::Yes, false) + }) { + let mut stmt = stmt.expect("an actual statement"); stmt.visit_attrs(|stmt_attrs| { attrs.prepend_to_nt_inner(stmt_attrs); }); - return Ok(Some(stmt.into_inner())); + return Ok(Some(stmt)); } if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) { @@ -129,11 +126,13 @@ impl<'a> Parser<'a> { self.mk_stmt(lo, StmtKind::Empty) } else if self.token != token::CloseDelim(Delimiter::Brace) { // Remainder are line-expr stmts. + let restrictions = + if force_full_expr { Restrictions::empty() } else { Restrictions::STMT_EXPR }; let e = match force_collect { - ForceCollect::Yes => self.collect_tokens_no_attrs(|this| { - this.parse_expr_res(Restrictions::STMT_EXPR, attrs) - })?, - ForceCollect::No => self.parse_expr_res(Restrictions::STMT_EXPR, attrs)?, + ForceCollect::Yes => { + self.collect_tokens_no_attrs(|this| this.parse_expr_res(restrictions, attrs))? + } + ForceCollect::No => self.parse_expr_res(restrictions, attrs)?, }; if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) { let bl = self.parse_block()?; @@ -471,7 +470,7 @@ impl<'a> Parser<'a> { // bar; // // which is valid in other languages, but not Rust. - match self.parse_stmt_without_recovery(false, ForceCollect::No) { + match self.parse_stmt_without_recovery(false, ForceCollect::No, false) { // If the next token is an open brace, e.g., we have: // // if expr other_expr { @@ -538,13 +537,9 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, can_be_struct_literal: bool, ) -> PResult<'a, (AttrVec, P)> { - if let Some(block) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Block, - NonterminalKind::Block, - ParseNtResult::Block(block), - block - ) { + if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| { + this.collect_tokens_no_attrs(|this| this.parse_block()) + }) { return Ok((AttrVec::new(), block)); } @@ -650,17 +645,23 @@ impl<'a> Parser<'a> { recover: AttemptLocalParseRecovery, ) -> PResult<'a, Option> { // Skip looking for a trailing semicolon when we have a metavar seq. - if let Some(stmt) = crate::maybe_reparse_metavar_seq!( - self, - NonterminalKind::Stmt, - NonterminalKind::Stmt, - ParseNtResult::Stmt(stmt), - stmt - ) { - return Ok(Some(stmt.into_inner())); + if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| { + // Why pass `true` for `force_full_expr`? Statement expressions are less expressive + // than "full" expressions, due to the `STMT_EXPR` restriction, and sometimes need + // parentheses. E.g. the "full" expression `match paren_around_match {} | true` when + // used in statement context must be written `(match paren_around_match {} | true)`. + // However, if the expression we are parsing in this statement context was pasted by a + // declarative macro, it may have come from a "full" expression context, and lack + // these parentheses. So we lift the `STMT_EXPR` restriction to ensure the statement + // will reparse successfully. + this.parse_stmt_without_recovery(false, ForceCollect::Yes, true) + }) { + let stmt = stmt.expect("an actual statement"); + return Ok(Some(stmt)); } - let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { + let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No, false)? + else { return Ok(None); }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b1d3c1663d957..a22c95b6f0f9c 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,4 +1,4 @@ -use super::{ParseNtResult, Parser, PathStyle, SeqSep, TokenType, Trailing}; +use super::{Parser, PathStyle, SeqSep, TokenType, Trailing}; use crate::errors::{ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, @@ -6,10 +6,10 @@ use crate::errors::{ HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow, }; -use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_reparse_metavar_seq}; +use crate::maybe_recover_from_interpolated_ty_qpath; use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, Delimiter, NonterminalKind, Token, TokenKind}; +use rustc_ast::token::{self, BinOpToken, Delimiter, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, @@ -251,13 +251,10 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes; maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); - if let Some(ty) = maybe_reparse_metavar_seq!( - self, - NonterminalKind::Ty, - NonterminalKind::Ty, - ParseNtResult::Ty(ty), - ty - ) { + + if let Some(ty) = self.eat_metavar_seq(MetaVarKind::Ty, |this| { + this.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover()) + }) { return Ok(ty); } diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 89169e10715b2..60c827fd03bbb 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind}; +use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; @@ -48,7 +48,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { parse_macro_arg!( Expr, - NonterminalKind::Expr, + NonterminalKind::Expr(Expr), |parser: &mut Parser<'b>| parser.parse_expr(), |x: ptr::P| Some(x) ); @@ -60,7 +60,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { ); parse_macro_arg!( Pat, - NonterminalKind::PatParam { inferred: false }, + NonterminalKind::Pat(PatParam { inferred: false }), |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None), |x: ptr::P| Some(x) );