Rollup merge of #122752 - nnethercote:Interpolated-cleanups, r=petrochenkov
Interpolated cleanups Various cleanups I made while working on attempts to remove `Interpolated`, that are worth merging now. Best reviewed one commit at a time. r? `@petrochenkov`
This commit is contained in:
commit
8b132109c4
17 changed files with 129 additions and 138 deletions
|
@ -850,13 +850,6 @@ pub(crate) struct StructLiteralNotAllowedHereSugg {
|
|||
pub right: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_invalid_interpolated_expression)]
|
||||
pub(crate) struct InvalidInterpolatedExpression {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_invalid_literal_suffix_on_tuple_index)]
|
||||
pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
|
||||
|
|
|
@ -3,11 +3,12 @@ use crate::errors::{
|
|||
SuffixedLiteralInAttribute,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::maybe_whole;
|
||||
|
||||
use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle};
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal};
|
||||
use rustc_ast::token::{self, Delimiter};
|
||||
use rustc_errors::{codes::*, Diag, PResult};
|
||||
use rustc_span::{sym, BytePos, Span};
|
||||
use thin_vec::ThinVec;
|
||||
|
@ -251,25 +252,15 @@ 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> {
|
||||
let item = match &self.token.kind {
|
||||
token::Interpolated(nt) => match &nt.0 {
|
||||
Nonterminal::NtMeta(item) => Some(item.clone().into_inner()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
maybe_whole!(self, NtMeta, |attr| attr.into_inner());
|
||||
|
||||
let do_parse = |this: &mut Self| {
|
||||
let path = this.parse_path(PathStyle::Mod)?;
|
||||
let args = this.parse_attr_args()?;
|
||||
Ok(ast::AttrItem { path, args, tokens: None })
|
||||
};
|
||||
Ok(if let Some(item) = item {
|
||||
self.bump();
|
||||
item
|
||||
} else {
|
||||
let do_parse = |this: &mut Self| {
|
||||
let path = this.parse_path(PathStyle::Mod)?;
|
||||
let args = this.parse_attr_args()?;
|
||||
Ok(ast::AttrItem { path, args, tokens: None })
|
||||
};
|
||||
// Attr items don't have attributes
|
||||
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }?
|
||||
})
|
||||
// Attr items don't have attributes
|
||||
if capture_tokens { self.collect_tokens_no_attrs(do_parse) } else { do_parse(self) }
|
||||
}
|
||||
|
||||
/// Parses attributes that appear after the opening of an item. These should
|
||||
|
@ -371,22 +362,18 @@ impl<'a> Parser<'a> {
|
|||
/// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ;
|
||||
/// ```
|
||||
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
|
||||
let nt_meta = match &self.token.kind {
|
||||
token::Interpolated(nt) => match &nt.0 {
|
||||
token::NtMeta(e) => Some(e.clone()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(item) = nt_meta {
|
||||
match item.meta(item.path.span) {
|
||||
// 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.0
|
||||
{
|
||||
match attr_item.meta(attr_item.path.span) {
|
||||
Some(meta) => {
|
||||
self.bump();
|
||||
return Ok(meta);
|
||||
}
|
||||
None => self.unexpected()?,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let lo = self.token.span;
|
||||
|
|
|
@ -2053,16 +2053,6 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
mk_lit_char: impl FnOnce(Symbol, Span) -> L,
|
||||
) -> PResult<'a, L> {
|
||||
if let token::Interpolated(nt) = &self.token.kind
|
||||
&& let token::NtExpr(e) | token::NtLiteral(e) = &nt.0
|
||||
&& matches!(e.kind, ExprKind::Err(_))
|
||||
{
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.create_err(errors::InvalidInterpolatedExpression { span: self.token.span });
|
||||
err.downgrade_to_delayed_bug();
|
||||
return Err(err);
|
||||
}
|
||||
let token = self.token.clone();
|
||||
let err = |self_: &Self| {
|
||||
let msg = format!("unexpected token: {}", super::token_descr(&token));
|
||||
|
|
|
@ -6,6 +6,7 @@ use super::{
|
|||
};
|
||||
use crate::errors::{self, MacroExpandsToAdtField};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::maybe_whole;
|
||||
use ast::token::IdentIsRaw;
|
||||
use rustc_ast::ast::*;
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -115,17 +116,10 @@ impl<'a> Parser<'a> {
|
|||
fn_parse_mode: FnParseMode,
|
||||
force_collect: ForceCollect,
|
||||
) -> PResult<'a, Option<Item>> {
|
||||
// Don't use `maybe_whole` so that we have precise control
|
||||
// over when we bump the parser
|
||||
if let token::Interpolated(nt) = &self.token.kind
|
||||
&& let token::NtItem(item) = &nt.0
|
||||
{
|
||||
let mut item = item.clone();
|
||||
self.bump();
|
||||
|
||||
maybe_whole!(self, NtItem, |item| {
|
||||
attrs.prepend_to_nt_inner(&mut item.attrs);
|
||||
return Ok(Some(item.into_inner()));
|
||||
};
|
||||
Some(item.into_inner())
|
||||
});
|
||||
|
||||
let item =
|
||||
self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| {
|
||||
|
|
|
@ -20,7 +20,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
|||
pub use path::PathStyle;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
|
||||
use rustc_ast::util::case::Case;
|
||||
|
@ -93,12 +93,13 @@ pub enum TrailingToken {
|
|||
#[macro_export]
|
||||
macro_rules! maybe_whole {
|
||||
($p:expr, $constructor:ident, |$x:ident| $e:expr) => {
|
||||
if let token::Interpolated(nt) = &$p.token.kind {
|
||||
if let token::$constructor(x) = &nt.0 {
|
||||
let $x = x.clone();
|
||||
$p.bump();
|
||||
return Ok($e);
|
||||
}
|
||||
if let token::Interpolated(nt) = &$p.token.kind
|
||||
&& let token::$constructor(x) = &nt.0
|
||||
{
|
||||
#[allow(unused_mut)]
|
||||
let mut $x = x.clone();
|
||||
$p.bump();
|
||||
return Ok($e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1407,7 +1408,7 @@ 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, |x| x.into_inner());
|
||||
maybe_whole!(self, NtVis, |vis| vis.into_inner());
|
||||
|
||||
if !self.eat_keyword(kw::Pub) {
|
||||
// We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
|
||||
|
@ -1584,8 +1585,21 @@ pub enum FlatToken {
|
|||
Empty,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseNtResult {
|
||||
Nt(Nonterminal),
|
||||
// Metavar captures of various kinds.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ParseNtResult<NtType> {
|
||||
Tt(TokenTree),
|
||||
Nt(NtType),
|
||||
}
|
||||
|
||||
impl<T> ParseNtResult<T> {
|
||||
pub fn map_nt<F, U>(self, mut f: F) -> ParseNtResult<U>
|
||||
where
|
||||
F: FnMut(T) -> U,
|
||||
{
|
||||
match self {
|
||||
ParseNtResult::Tt(tt) => ParseNtResult::Tt(tt),
|
||||
ParseNtResult::Nt(nt) => ParseNtResult::Nt(f(nt)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
|
||||
use rustc_ast::token::{self, Delimiter, Nonterminal, Nonterminal::*, NonterminalKind, Token};
|
||||
use rustc_ast::HasTokens;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::PResult;
|
||||
|
@ -66,15 +66,14 @@ impl<'a> Parser<'a> {
|
|||
token::Interpolated(nt) => may_be_ident(&nt.0),
|
||||
_ => false,
|
||||
},
|
||||
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
|
||||
match &token.kind {
|
||||
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind {
|
||||
token::Ident(..) | // box, ref, mut, and other identifiers (can stricten)
|
||||
token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern
|
||||
token::OpenDelim(Delimiter::Bracket) | // slice pattern
|
||||
token::BinOp(token::And) | // reference
|
||||
token::BinOp(token::Minus) | // negative literal
|
||||
token::AndAnd | // double reference
|
||||
token::Literal(_) | // literal
|
||||
token::Literal(_) | // literal
|
||||
token::DotDot | // range pattern (future compat)
|
||||
token::DotDotDot | // range pattern (future compat)
|
||||
token::ModSep | // path
|
||||
|
@ -84,8 +83,7 @@ impl<'a> Parser<'a> {
|
|||
token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
|
||||
token::Interpolated(nt) => may_be_ident(&nt.0),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
},
|
||||
NonterminalKind::Lifetime => match &token.kind {
|
||||
token::Lifetime(_) => true,
|
||||
token::Interpolated(nt) => {
|
||||
|
@ -102,7 +100,10 @@ impl<'a> Parser<'a> {
|
|||
/// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
|
||||
/// site.
|
||||
#[inline]
|
||||
pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
|
||||
pub fn parse_nonterminal(
|
||||
&mut self,
|
||||
kind: NonterminalKind,
|
||||
) -> PResult<'a, ParseNtResult<Nonterminal>> {
|
||||
// A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
|
||||
// which requires having captured tokens available. Since we cannot determine
|
||||
// in advance whether or not a proc-macro will be (transitively) invoked,
|
||||
|
|
|
@ -435,7 +435,7 @@ impl<'a> Parser<'a> {
|
|||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, P<Pat>> {
|
||||
maybe_recover_from_interpolated_ty_qpath!(self, true);
|
||||
maybe_whole!(self, NtPat, |x| x);
|
||||
maybe_whole!(self, NtPat, |pat| pat);
|
||||
|
||||
let mut lo = self.token.span;
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ impl<'a> Parser<'a> {
|
|||
}))
|
||||
}
|
||||
|
||||
/// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of whether
|
||||
/// or not we have attributes
|
||||
/// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
|
||||
/// whether or not we have attributes.
|
||||
// Public for `cfg_eval` macro expansion.
|
||||
pub fn parse_stmt_without_recovery(
|
||||
&mut self,
|
||||
|
@ -51,18 +51,12 @@ impl<'a> Parser<'a> {
|
|||
let attrs = self.parse_outer_attributes()?;
|
||||
let lo = self.token.span;
|
||||
|
||||
// Don't use `maybe_whole` so that we have precise control
|
||||
// over when we bump the parser
|
||||
if let token::Interpolated(nt) = &self.token.kind
|
||||
&& let token::NtStmt(stmt) = &nt.0
|
||||
{
|
||||
let mut stmt = stmt.clone();
|
||||
self.bump();
|
||||
maybe_whole!(self, NtStmt, |stmt| {
|
||||
stmt.visit_attrs(|stmt_attrs| {
|
||||
attrs.prepend_to_nt_inner(stmt_attrs);
|
||||
});
|
||||
return Ok(Some(stmt.into_inner()));
|
||||
}
|
||||
Some(stmt.into_inner())
|
||||
});
|
||||
|
||||
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
|
||||
self.bump();
|
||||
|
@ -539,7 +533,7 @@ impl<'a> Parser<'a> {
|
|||
blk_mode: BlockCheckMode,
|
||||
can_be_struct_literal: bool,
|
||||
) -> PResult<'a, (AttrVec, P<Block>)> {
|
||||
maybe_whole!(self, NtBlock, |x| (AttrVec::new(), x));
|
||||
maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block));
|
||||
|
||||
let maybe_ident = self.prev_token.clone();
|
||||
self.maybe_recover_unexpected_block_label();
|
||||
|
@ -643,7 +637,7 @@ impl<'a> Parser<'a> {
|
|||
recover: AttemptLocalParseRecovery,
|
||||
) -> PResult<'a, Option<Stmt>> {
|
||||
// Skip looking for a trailing semicolon when we have an interpolated statement.
|
||||
maybe_whole!(self, NtStmt, |x| Some(x.into_inner()));
|
||||
maybe_whole!(self, NtStmt, |stmt| Some(stmt.into_inner()));
|
||||
|
||||
let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else {
|
||||
return Ok(None);
|
||||
|
|
|
@ -250,7 +250,7 @@ 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, |x| x);
|
||||
maybe_whole!(self, NtTy, |ty| ty);
|
||||
|
||||
let lo = self.token.span;
|
||||
let mut impl_dyn_multi = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue