Auto merge of #146221 - camsteffen:ast-boxes, r=cjgillot
Remove boxes from ast list elements Less indirection should be better perf.
This commit is contained in:
commit
f5242367f4
16 changed files with 150 additions and 126 deletions
|
|
@ -869,11 +869,11 @@ pub enum PatKind {
|
|||
Struct(Option<Box<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
|
||||
|
||||
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
|
||||
TupleStruct(Option<Box<QSelf>>, Path, ThinVec<Box<Pat>>),
|
||||
TupleStruct(Option<Box<QSelf>>, Path, ThinVec<Pat>),
|
||||
|
||||
/// An or-pattern `A | B | C`.
|
||||
/// Invariant: `pats.len() >= 2`.
|
||||
Or(ThinVec<Box<Pat>>),
|
||||
Or(ThinVec<Pat>),
|
||||
|
||||
/// A possibly qualified path pattern.
|
||||
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
|
||||
|
|
@ -882,7 +882,7 @@ pub enum PatKind {
|
|||
Path(Option<Box<QSelf>>, Path),
|
||||
|
||||
/// A tuple pattern (`(a, b)`).
|
||||
Tuple(ThinVec<Box<Pat>>),
|
||||
Tuple(ThinVec<Pat>),
|
||||
|
||||
/// A `box` pattern.
|
||||
Box(Box<Pat>),
|
||||
|
|
@ -900,7 +900,7 @@ pub enum PatKind {
|
|||
Range(Option<Box<Expr>>, Option<Box<Expr>>, Spanned<RangeEnd>),
|
||||
|
||||
/// A slice pattern `[a, b, c]`.
|
||||
Slice(ThinVec<Box<Pat>>),
|
||||
Slice(ThinVec<Pat>),
|
||||
|
||||
/// A rest pattern `..`.
|
||||
///
|
||||
|
|
@ -2579,7 +2579,7 @@ pub enum TyPatKind {
|
|||
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
|
||||
Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
|
||||
|
||||
Or(ThinVec<Box<TyPat>>),
|
||||
Or(ThinVec<TyPat>),
|
||||
|
||||
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
|
||||
Err(ErrorGuaranteed),
|
||||
|
|
|
|||
|
|
@ -389,9 +389,9 @@ macro_rules! common_visitor_and_walkers {
|
|||
ThinVec<(NodeId, Path)>,
|
||||
ThinVec<PathSegment>,
|
||||
ThinVec<PreciseCapturingArg>,
|
||||
ThinVec<Box<Pat>>,
|
||||
ThinVec<Pat>,
|
||||
ThinVec<Box<Ty>>,
|
||||
ThinVec<Box<TyPat>>,
|
||||
ThinVec<TyPat>,
|
||||
);
|
||||
|
||||
// This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn lower_pat_tuple(
|
||||
&mut self,
|
||||
pats: &[Box<Pat>],
|
||||
pats: &[Pat],
|
||||
ctx: &str,
|
||||
) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
|
||||
let mut elems = Vec::with_capacity(pats.len());
|
||||
|
|
@ -209,7 +209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// When encountering `($binding_mode $ident @)? ..` (`slice`),
|
||||
/// this is interpreted as a sub-slice pattern semantically.
|
||||
/// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
|
||||
fn lower_pat_slice(&mut self, pats: &[Box<Pat>]) -> hir::PatKind<'hir> {
|
||||
fn lower_pat_slice(&mut self, pats: &[Pat]) -> hir::PatKind<'hir> {
|
||||
let mut before = Vec::new();
|
||||
let mut after = Vec::new();
|
||||
let mut slice = None;
|
||||
|
|
|
|||
|
|
@ -1507,7 +1507,7 @@ impl<'a> TraitDef<'a> {
|
|||
struct_def: &'a VariantData,
|
||||
prefixes: &[String],
|
||||
by_ref: ByRef,
|
||||
) -> ThinVec<Box<ast::Pat>> {
|
||||
) -> ThinVec<ast::Pat> {
|
||||
prefixes
|
||||
.iter()
|
||||
.map(|prefix| {
|
||||
|
|
@ -1543,7 +1543,7 @@ impl<'a> TraitDef<'a> {
|
|||
attrs: ast::AttrVec::new(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: pat.span.with_ctxt(self.span.ctxt()),
|
||||
pat,
|
||||
pat: Box::new(pat),
|
||||
is_placeholder: false,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fn parse_pat_ty<'a>(
|
|||
|
||||
let pat = pat_to_ty_pat(
|
||||
cx,
|
||||
*parser.parse_pat_no_top_guard(
|
||||
parser.parse_pat_no_top_guard(
|
||||
None,
|
||||
RecoverComma::No,
|
||||
RecoverColon::No,
|
||||
|
|
@ -44,14 +44,14 @@ fn parse_pat_ty<'a>(
|
|||
parser.unexpected()?;
|
||||
}
|
||||
|
||||
Ok((ty, pat))
|
||||
Ok((ty, Box::new(pat)))
|
||||
}
|
||||
|
||||
fn ty_pat(kind: TyPatKind, span: Span) -> Box<TyPat> {
|
||||
Box::new(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
|
||||
fn ty_pat(kind: TyPatKind, span: Span) -> TyPat {
|
||||
TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None }
|
||||
}
|
||||
|
||||
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> Box<TyPat> {
|
||||
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> TyPat {
|
||||
let kind = match pat.kind {
|
||||
ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
|
||||
start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
|
|
@ -59,7 +59,7 @@ fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> Box<TyPat> {
|
|||
include_end,
|
||||
),
|
||||
ast::PatKind::Or(variants) => {
|
||||
TyPatKind::Or(variants.into_iter().map(|pat| pat_to_ty_pat(cx, *pat)).collect())
|
||||
TyPatKind::Or(variants.into_iter().map(|pat| pat_to_ty_pat(cx, pat)).collect())
|
||||
}
|
||||
ast::PatKind::Err(guar) => TyPatKind::Err(guar),
|
||||
_ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
};
|
||||
let local = Box::new(ast::Local {
|
||||
super_: None,
|
||||
pat,
|
||||
pat: Box::new(pat),
|
||||
ty,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: LocalKind::Init(ex),
|
||||
|
|
@ -249,7 +249,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
pub fn stmt_let_type_only(&self, span: Span, ty: Box<ast::Ty>) -> ast::Stmt {
|
||||
let local = Box::new(ast::Local {
|
||||
super_: None,
|
||||
pat: self.pat_wild(span),
|
||||
pat: Box::new(self.pat_wild(span)),
|
||||
ty: Some(ty),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: LocalKind::Decl,
|
||||
|
|
@ -528,16 +528,16 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
|
||||
}
|
||||
|
||||
pub fn pat(&self, span: Span, kind: PatKind) -> Box<ast::Pat> {
|
||||
Box::new(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
|
||||
pub fn pat(&self, span: Span, kind: PatKind) -> ast::Pat {
|
||||
ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None }
|
||||
}
|
||||
pub fn pat_wild(&self, span: Span) -> Box<ast::Pat> {
|
||||
pub fn pat_wild(&self, span: Span) -> ast::Pat {
|
||||
self.pat(span, PatKind::Wild)
|
||||
}
|
||||
pub fn pat_lit(&self, span: Span, expr: Box<ast::Expr>) -> Box<ast::Pat> {
|
||||
pub fn pat_lit(&self, span: Span, expr: Box<ast::Expr>) -> ast::Pat {
|
||||
self.pat(span, PatKind::Expr(expr))
|
||||
}
|
||||
pub fn pat_ident(&self, span: Span, ident: Ident) -> Box<ast::Pat> {
|
||||
pub fn pat_ident(&self, span: Span, ident: Ident) -> ast::Pat {
|
||||
self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
|
||||
}
|
||||
|
||||
|
|
@ -546,19 +546,19 @@ impl<'a> ExtCtxt<'a> {
|
|||
span: Span,
|
||||
ident: Ident,
|
||||
ann: ast::BindingMode,
|
||||
) -> Box<ast::Pat> {
|
||||
) -> ast::Pat {
|
||||
let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
|
||||
self.pat(span, pat)
|
||||
}
|
||||
pub fn pat_path(&self, span: Span, path: ast::Path) -> Box<ast::Pat> {
|
||||
pub fn pat_path(&self, span: Span, path: ast::Path) -> ast::Pat {
|
||||
self.pat(span, PatKind::Path(None, path))
|
||||
}
|
||||
pub fn pat_tuple_struct(
|
||||
&self,
|
||||
span: Span,
|
||||
path: ast::Path,
|
||||
subpats: ThinVec<Box<ast::Pat>>,
|
||||
) -> Box<ast::Pat> {
|
||||
subpats: ThinVec<ast::Pat>,
|
||||
) -> ast::Pat {
|
||||
self.pat(span, PatKind::TupleStruct(None, path, subpats))
|
||||
}
|
||||
pub fn pat_struct(
|
||||
|
|
@ -566,23 +566,23 @@ impl<'a> ExtCtxt<'a> {
|
|||
span: Span,
|
||||
path: ast::Path,
|
||||
field_pats: ThinVec<ast::PatField>,
|
||||
) -> Box<ast::Pat> {
|
||||
) -> ast::Pat {
|
||||
self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
|
||||
}
|
||||
pub fn pat_tuple(&self, span: Span, pats: ThinVec<Box<ast::Pat>>) -> Box<ast::Pat> {
|
||||
pub fn pat_tuple(&self, span: Span, pats: ThinVec<ast::Pat>) -> ast::Pat {
|
||||
self.pat(span, PatKind::Tuple(pats))
|
||||
}
|
||||
|
||||
pub fn pat_some(&self, span: Span, pat: Box<ast::Pat>) -> Box<ast::Pat> {
|
||||
pub fn pat_some(&self, span: Span, pat: ast::Pat) -> ast::Pat {
|
||||
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
|
||||
let path = self.path_global(span, some);
|
||||
self.pat_tuple_struct(span, path, thin_vec![pat])
|
||||
}
|
||||
|
||||
pub fn arm(&self, span: Span, pat: Box<ast::Pat>, expr: Box<ast::Expr>) -> ast::Arm {
|
||||
pub fn arm(&self, span: Span, pat: ast::Pat, expr: Box<ast::Expr>) -> ast::Arm {
|
||||
ast::Arm {
|
||||
attrs: AttrVec::new(),
|
||||
pat,
|
||||
pat: Box::new(pat),
|
||||
guard: None,
|
||||
body: Some(expr),
|
||||
span,
|
||||
|
|
@ -661,11 +661,11 @@ impl<'a> ExtCtxt<'a> {
|
|||
}
|
||||
|
||||
pub fn param(&self, span: Span, ident: Ident, ty: Box<ast::Ty>) -> ast::Param {
|
||||
let arg_pat = self.pat_ident(span, ident);
|
||||
let pat = Box::new(self.pat_ident(span, ident));
|
||||
ast::Param {
|
||||
attrs: AttrVec::default(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
pat: arg_pat,
|
||||
pat,
|
||||
span,
|
||||
ty,
|
||||
is_placeholder: false,
|
||||
|
|
|
|||
|
|
@ -1152,12 +1152,12 @@ pub fn parse_ast_fragment<'a>(
|
|||
}
|
||||
}
|
||||
AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
|
||||
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard(
|
||||
AstFragmentKind::Pat => AstFragment::Pat(Box::new(this.parse_pat_allow_top_guard(
|
||||
None,
|
||||
RecoverComma::No,
|
||||
RecoverColon::Yes,
|
||||
CommaRecoveryMode::LikelyTuple,
|
||||
)?),
|
||||
)?)),
|
||||
AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
|
||||
AstFragmentKind::Arms
|
||||
| AstFragmentKind::ExprFields
|
||||
|
|
|
|||
|
|
@ -73,6 +73,16 @@ pub(super) trait RecoverQPath: Sized + 'static {
|
|||
fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self;
|
||||
}
|
||||
|
||||
impl<T: RecoverQPath> RecoverQPath for Box<T> {
|
||||
const PATH_STYLE: PathStyle = T::PATH_STYLE;
|
||||
fn to_ty(&self) -> Option<Box<Ty>> {
|
||||
T::to_ty(self)
|
||||
}
|
||||
fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
|
||||
Box::new(T::recovered(qself, path))
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverQPath for Ty {
|
||||
const PATH_STYLE: PathStyle = PathStyle::Type;
|
||||
fn to_ty(&self) -> Option<Box<Ty>> {
|
||||
|
|
@ -1833,17 +1843,19 @@ impl<'a> Parser<'a> {
|
|||
/// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
|
||||
pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
|
||||
&mut self,
|
||||
base: Box<T>,
|
||||
) -> PResult<'a, Box<T>> {
|
||||
if !self.may_recover() {
|
||||
return Ok(base);
|
||||
}
|
||||
|
||||
base: T,
|
||||
) -> PResult<'a, T> {
|
||||
// Do not add `::` to expected tokens.
|
||||
if self.token == token::PathSep {
|
||||
if let Some(ty) = base.to_ty() {
|
||||
return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
|
||||
}
|
||||
if self.may_recover() && self.token == token::PathSep {
|
||||
return self.recover_from_bad_qpath(base);
|
||||
}
|
||||
Ok(base)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T) -> PResult<'a, T> {
|
||||
if let Some(ty) = base.to_ty() {
|
||||
return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
|
||||
}
|
||||
Ok(base)
|
||||
}
|
||||
|
|
@ -1854,7 +1866,7 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
ty_span: Span,
|
||||
ty: Box<Ty>,
|
||||
) -> PResult<'a, Box<T>> {
|
||||
) -> PResult<'a, T> {
|
||||
self.expect(exp!(PathSep))?;
|
||||
|
||||
let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
|
||||
|
|
@ -1867,7 +1879,7 @@ impl<'a> Parser<'a> {
|
|||
});
|
||||
|
||||
let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
|
||||
Ok(Box::new(T::recovered(Some(Box::new(QSelf { ty, path_span, position: 0 })), path)))
|
||||
Ok(T::recovered(Some(Box::new(QSelf { ty, path_span, position: 0 })), path))
|
||||
}
|
||||
|
||||
/// This function gets called in places where a semicolon is NOT expected and if there's a
|
||||
|
|
@ -2360,6 +2372,7 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
}
|
||||
|
||||
#[cold]
|
||||
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
|
||||
let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
|
||||
self.expect(exp!(Colon))?;
|
||||
|
|
@ -2740,11 +2753,12 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Some special error handling for the "top-level" patterns in a match arm,
|
||||
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
|
||||
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
|
||||
#[cold]
|
||||
pub(crate) fn recover_colon_colon_in_pat_typo(
|
||||
&mut self,
|
||||
mut first_pat: Box<Pat>,
|
||||
mut first_pat: Pat,
|
||||
expected: Option<Expected>,
|
||||
) -> Box<Pat> {
|
||||
) -> Pat {
|
||||
if token::Colon != self.token.kind {
|
||||
return first_pat;
|
||||
}
|
||||
|
|
@ -2925,7 +2939,11 @@ impl<'a> Parser<'a> {
|
|||
if self.token != token::Comma {
|
||||
return Ok(());
|
||||
}
|
||||
self.recover_unexpected_comma(lo, rt)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn recover_unexpected_comma(&mut self, lo: Span, rt: CommaRecoveryMode) -> PResult<'a, ()> {
|
||||
// An unexpected comma after a top-level pattern is a clue that the
|
||||
// user (perhaps more accustomed to some other language) forgot the
|
||||
// parentheses in what should have been a tuple pattern; return a
|
||||
|
|
|
|||
|
|
@ -2587,7 +2587,7 @@ impl<'a> Parser<'a> {
|
|||
let lo = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
|
||||
let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?;
|
||||
let pat = Box::new(this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?);
|
||||
let ty = if this.eat(exp!(Colon)) {
|
||||
this.parse_ty()?
|
||||
} else {
|
||||
|
|
@ -2781,7 +2781,7 @@ impl<'a> Parser<'a> {
|
|||
let (expr, _) =
|
||||
self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?;
|
||||
let span = lo.to(expr.span);
|
||||
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
|
||||
Ok(self.mk_expr(span, ExprKind::Let(Box::new(pat), expr, span, recovered)))
|
||||
}
|
||||
|
||||
/// Parses an `else { ... }` expression (`else` token already eaten).
|
||||
|
|
@ -2897,7 +2897,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
// Public to use it for custom `for` expressions in rustfmt forks like https://github.com/tucant/rustfmt
|
||||
pub fn parse_for_head(&mut self) -> PResult<'a, (Box<Pat>, Box<Expr>)> {
|
||||
pub fn parse_for_head(&mut self) -> PResult<'a, (Pat, Box<Expr>)> {
|
||||
let begin_paren = if self.token == token::OpenParen {
|
||||
// Record whether we are about to parse `for (`.
|
||||
// This is used below for recovery in case of `for ( $stuff ) $block`
|
||||
|
|
@ -2974,6 +2974,7 @@ impl<'a> Parser<'a> {
|
|||
let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For };
|
||||
|
||||
let (pat, expr) = self.parse_for_head()?;
|
||||
let pat = Box::new(pat);
|
||||
// Recover from missing expression in `for` loop
|
||||
if matches!(expr.kind, ExprKind::Block(..))
|
||||
&& self.token.kind != token::OpenBrace
|
||||
|
|
@ -3142,7 +3143,7 @@ impl<'a> Parser<'a> {
|
|||
// Always push at least one arm to make the match non-empty
|
||||
arms.push(Arm {
|
||||
attrs: Default::default(),
|
||||
pat: self.mk_pat(span, ast::PatKind::Err(guar)),
|
||||
pat: Box::new(self.mk_pat(span, ast::PatKind::Err(guar))),
|
||||
guard: None,
|
||||
body: Some(self.mk_expr_err(span, guar)),
|
||||
span,
|
||||
|
|
@ -3246,6 +3247,7 @@ impl<'a> Parser<'a> {
|
|||
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
|
||||
let lo = this.token.span;
|
||||
let (pat, guard) = this.parse_match_arm_pat_and_guard()?;
|
||||
let pat = Box::new(pat);
|
||||
|
||||
let span_before_body = this.prev_token.span;
|
||||
let arm_body;
|
||||
|
|
@ -3468,7 +3470,7 @@ impl<'a> Parser<'a> {
|
|||
Ok(Some(cond))
|
||||
}
|
||||
|
||||
fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Box<Pat>, Option<Box<Expr>>)> {
|
||||
fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
|
||||
if self.token == token::OpenParen {
|
||||
let left = self.token.span;
|
||||
let pat = self.parse_pat_no_top_guard(
|
||||
|
|
|
|||
|
|
@ -3111,7 +3111,7 @@ impl<'a> Parser<'a> {
|
|||
match ty {
|
||||
Ok(ty) => {
|
||||
let pat = this.mk_pat(ty.span, PatKind::Missing);
|
||||
(pat, ty)
|
||||
(Box::new(pat), ty)
|
||||
}
|
||||
// If this is a C-variadic argument and we hit an error, return the error.
|
||||
Err(err) if this.token == token::DotDotDot => return Err(err),
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ impl<'a> Parser<'a> {
|
|||
RecoverColon::No,
|
||||
CommaRecoveryMode::EitherTupleOrPipe,
|
||||
),
|
||||
})?,
|
||||
})
|
||||
.map(Box::new)?,
|
||||
pat_kind,
|
||||
)),
|
||||
NonterminalKind::Expr(expr_kind) => {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ impl<'a> Parser<'a> {
|
|||
rc: RecoverComma,
|
||||
ra: RecoverColon,
|
||||
rt: CommaRecoveryMode,
|
||||
) -> PResult<'a, Box<Pat>> {
|
||||
) -> PResult<'a, Pat> {
|
||||
let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;
|
||||
|
||||
if self.eat_keyword(exp!(If)) {
|
||||
|
|
@ -115,7 +115,7 @@ impl<'a> Parser<'a> {
|
|||
// Feature-gate guard patterns
|
||||
self.psess.gated_spans.gate(sym::guard_patterns, cond.span);
|
||||
let span = pat.span.to(cond.span);
|
||||
Ok(self.mk_pat(span, PatKind::Guard(pat, cond)))
|
||||
Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), cond)))
|
||||
} else {
|
||||
Ok(pat)
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
expected: Option<Expected>,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, Box<Pat>> {
|
||||
) -> PResult<'a, Pat> {
|
||||
self.parse_pat_with_range_pat(true, expected, syntax_loc)
|
||||
}
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ impl<'a> Parser<'a> {
|
|||
rc: RecoverComma,
|
||||
ra: RecoverColon,
|
||||
rt: CommaRecoveryMode,
|
||||
) -> PResult<'a, Box<Pat>> {
|
||||
) -> PResult<'a, Pat> {
|
||||
self.parse_pat_no_top_guard_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat)
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ impl<'a> Parser<'a> {
|
|||
ra: RecoverColon,
|
||||
rt: CommaRecoveryMode,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, (Box<Pat>, bool)> {
|
||||
) -> PResult<'a, (Pat, bool)> {
|
||||
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
|
||||
// suggestions (which bothers rustfix).
|
||||
//
|
||||
|
|
@ -199,8 +199,8 @@ impl<'a> Parser<'a> {
|
|||
// This complicated procedure is done purely for diagnostics UX.
|
||||
|
||||
// Check if the user wrote `foo:bar` instead of `foo::bar`.
|
||||
if ra == RecoverColon::Yes {
|
||||
first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, expected);
|
||||
if ra == RecoverColon::Yes && token::Colon == self.token.kind {
|
||||
first_pat = self.recover_colon_colon_in_pat_typo(first_pat, expected);
|
||||
}
|
||||
|
||||
if let Some(leading_vert_span) = leading_vert_span {
|
||||
|
|
@ -263,6 +263,7 @@ impl<'a> Parser<'a> {
|
|||
CommaRecoveryMode::LikelyTuple,
|
||||
Some(syntax_loc),
|
||||
)?;
|
||||
let pat = Box::new(pat);
|
||||
let colon = self.eat(exp!(Colon));
|
||||
|
||||
if let PatKind::Or(pats) = &pat.kind {
|
||||
|
|
@ -686,7 +687,7 @@ impl<'a> Parser<'a> {
|
|||
PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt);
|
||||
}
|
||||
|
||||
fn eat_metavar_pat(&mut self) -> Option<Box<Pat>> {
|
||||
fn eat_metavar_pat(&mut self) -> Option<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 { .. })),
|
||||
|
|
@ -714,7 +715,7 @@ impl<'a> Parser<'a> {
|
|||
allow_range_pat: bool,
|
||||
expected: Option<Expected>,
|
||||
syntax_loc: Option<PatternLocation>,
|
||||
) -> PResult<'a, Box<Pat>> {
|
||||
) -> PResult<'a, Pat> {
|
||||
maybe_recover_from_interpolated_ty_qpath!(self, true);
|
||||
|
||||
if let Some(pat) = self.eat_metavar_pat() {
|
||||
|
|
@ -873,9 +874,12 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
let pat = self.mk_pat(lo.to(self.prev_token.span), pat);
|
||||
let pat = self.maybe_recover_from_bad_qpath(pat)?;
|
||||
let pat = self.recover_intersection_pat(pat)?;
|
||||
let mut pat = self.mk_pat(lo.to(self.prev_token.span), pat);
|
||||
|
||||
pat = self.maybe_recover_from_bad_qpath(pat)?;
|
||||
if self.eat_noexpect(&token::At) {
|
||||
pat = self.recover_intersection_pat(pat)?;
|
||||
}
|
||||
|
||||
if !allow_range_pat {
|
||||
self.ban_pat_range_if_ambiguous(&pat)
|
||||
|
|
@ -921,14 +925,8 @@ impl<'a> Parser<'a> {
|
|||
/// e.g. [F#][and] where they are called AND-patterns.
|
||||
///
|
||||
/// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
|
||||
fn recover_intersection_pat(&mut self, lhs: Box<Pat>) -> PResult<'a, Box<Pat>> {
|
||||
if self.token != token::At {
|
||||
// Next token is not `@` so it's not going to be an intersection pattern.
|
||||
return Ok(lhs);
|
||||
}
|
||||
|
||||
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
|
||||
self.bump(); // `@`
|
||||
#[cold]
|
||||
fn recover_intersection_pat(&mut self, lhs: Pat) -> PResult<'a, Pat> {
|
||||
let mut rhs = self.parse_pat_no_top_alt(None, None)?;
|
||||
let whole_span = lhs.span.to(rhs.span);
|
||||
|
||||
|
|
@ -937,7 +935,7 @@ impl<'a> Parser<'a> {
|
|||
let lhs_span = lhs.span;
|
||||
// Move the LHS into the RHS as a subpattern.
|
||||
// The RHS is now the full pattern.
|
||||
*sub = Some(lhs);
|
||||
*sub = Some(Box::new(lhs));
|
||||
|
||||
self.dcx().emit_err(PatternOnWrongSideOfAt {
|
||||
whole_span,
|
||||
|
|
@ -994,7 +992,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let mutbl = self.parse_mutability();
|
||||
let subpat = self.parse_pat_with_range_pat(false, expected, None)?;
|
||||
Ok(PatKind::Ref(subpat, mutbl))
|
||||
Ok(PatKind::Ref(Box::new(subpat), mutbl))
|
||||
}
|
||||
|
||||
/// Parse a tuple or parenthesis pattern.
|
||||
|
|
@ -1052,7 +1050,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
// (pat) with optional parentheses
|
||||
_ => PatKind::Paren(pat),
|
||||
_ => PatKind::Paren(Box::new(pat)),
|
||||
}
|
||||
} else {
|
||||
PatKind::Tuple(fields)
|
||||
|
|
@ -1103,7 +1101,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Turn all by-value immutable bindings in a pattern into mutable bindings.
|
||||
/// Returns `true` if any change was made.
|
||||
fn make_all_value_bindings_mutable(pat: &mut Box<Pat>) -> bool {
|
||||
fn make_all_value_bindings_mutable(pat: &mut Pat) -> bool {
|
||||
struct AddMut(bool);
|
||||
impl MutVisitor for AddMut {
|
||||
fn visit_pat(&mut self, pat: &mut Pat) {
|
||||
|
|
@ -1159,7 +1157,7 @@ impl<'a> Parser<'a> {
|
|||
&mut self,
|
||||
err: Diag<'a>,
|
||||
expected: Option<Expected>,
|
||||
) -> PResult<'a, Box<Pat>> {
|
||||
) -> PResult<'a, Pat> {
|
||||
err.cancel();
|
||||
|
||||
let expected = Expected::to_string_or_fallback(expected);
|
||||
|
|
@ -1362,7 +1360,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
let sub = if self.eat(exp!(At)) {
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
|
||||
Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -1451,12 +1449,14 @@ impl<'a> Parser<'a> {
|
|||
self.parse_builtin(|self_, _lo, ident| {
|
||||
Ok(match ident.name {
|
||||
// builtin#deref(PAT)
|
||||
sym::deref => Some(ast::PatKind::Deref(self_.parse_pat_allow_top_guard(
|
||||
None,
|
||||
RecoverComma::Yes,
|
||||
RecoverColon::Yes,
|
||||
CommaRecoveryMode::LikelyTuple,
|
||||
)?)),
|
||||
sym::deref => {
|
||||
Some(ast::PatKind::Deref(Box::new(self_.parse_pat_allow_top_guard(
|
||||
None,
|
||||
RecoverComma::Yes,
|
||||
RecoverColon::Yes,
|
||||
CommaRecoveryMode::LikelyTuple,
|
||||
)?)))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
})
|
||||
|
|
@ -1478,14 +1478,14 @@ impl<'a> Parser<'a> {
|
|||
// We cannot use `parse_pat_ident()` since it will complain `box`
|
||||
// is not an identifier.
|
||||
let sub = if self.eat(exp!(At)) {
|
||||
Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)
|
||||
Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(PatKind::Ident(BindingMode::NONE, Ident::new(kw::Box, box_span), sub))
|
||||
} else {
|
||||
let pat = self.parse_pat_with_range_pat(false, None, None)?;
|
||||
let pat = Box::new(self.parse_pat_with_range_pat(false, None, None)?);
|
||||
self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
|
||||
Ok(PatKind::Box(pat))
|
||||
}
|
||||
|
|
@ -1745,14 +1745,17 @@ impl<'a> Parser<'a> {
|
|||
hi = self.prev_token.span;
|
||||
let ann = BindingMode(by_ref, mutability);
|
||||
let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname);
|
||||
let subpat =
|
||||
if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat };
|
||||
let subpat = if is_box {
|
||||
self.mk_pat(lo.to(hi), PatKind::Box(Box::new(fieldpat)))
|
||||
} else {
|
||||
fieldpat
|
||||
};
|
||||
(subpat, fieldname, true)
|
||||
};
|
||||
|
||||
Ok(PatField {
|
||||
ident: fieldname,
|
||||
pat: subpat,
|
||||
pat: Box::new(subpat),
|
||||
is_shorthand,
|
||||
attrs,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
|
@ -1761,11 +1764,11 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Box<Pat> {
|
||||
pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Pat {
|
||||
self.mk_pat(span, PatKind::Ident(ann, ident, None))
|
||||
}
|
||||
|
||||
pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> Box<Pat> {
|
||||
Box::new(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
|
||||
pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> Pat {
|
||||
Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3664,7 +3664,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
/// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
|
||||
fn compute_and_check_or_pat_binding_map(
|
||||
&mut self,
|
||||
pats: &[Box<Pat>],
|
||||
pats: &[Pat],
|
||||
) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
|
||||
let mut missing_vars = FxIndexMap::default();
|
||||
let mut inconsistent_vars = FxIndexMap::default();
|
||||
|
|
@ -3679,11 +3679,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
// 2) Record any missing bindings or binding mode inconsistencies.
|
||||
for (map_outer, pat_outer) in not_never_pats.iter() {
|
||||
for &(ref map_outer, pat_outer) in not_never_pats.iter() {
|
||||
// Check against all arms except for the same pattern which is always self-consistent.
|
||||
let inners = not_never_pats.iter().filter(|(_, pat)| pat.id != pat_outer.id);
|
||||
|
||||
for (map, pat) in inners {
|
||||
for &(ref map, pat) in inners {
|
||||
for (&name, binding_inner) in map {
|
||||
match map_outer.get(&name) {
|
||||
None => {
|
||||
|
|
@ -3695,8 +3695,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
target: Default::default(),
|
||||
could_be_path: name.as_str().starts_with(char::is_uppercase),
|
||||
});
|
||||
binding_error.origin.push((binding_inner.span, (***pat).clone()));
|
||||
binding_error.target.push((***pat_outer).clone());
|
||||
binding_error.origin.push((binding_inner.span, pat.clone()));
|
||||
binding_error.target.push(pat_outer.clone());
|
||||
}
|
||||
Some(binding_outer) => {
|
||||
if binding_outer.annotation != binding_inner.annotation {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ macro_rules! always_pat {
|
|||
/// Focus on `focus_idx` in `alternatives`,
|
||||
/// attempting to extend it with elements of the same constructor `C`
|
||||
/// in `alternatives[focus_idx + 1..]`.
|
||||
fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Box<Pat>>, focus_idx: usize) -> bool {
|
||||
fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Pat>, focus_idx: usize) -> bool {
|
||||
// Extract the kind; we'll need to make some changes in it.
|
||||
let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, Wild);
|
||||
// We'll focus on `alternatives[focus_idx]`,
|
||||
|
|
@ -251,20 +251,20 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Box<Pat>>, focus_idx:
|
|||
Box(target) => extend_with_matching(
|
||||
target, start, alternatives,
|
||||
|k| matches!(k, Box(_)),
|
||||
|k| always_pat!(k, Box(p) => p),
|
||||
|k| always_pat!(k, Box(p) => *p),
|
||||
),
|
||||
// Transform `&mut x | ... | &mut y` into `&mut (x | y)`.
|
||||
Ref(target, Mutability::Mut) => extend_with_matching(
|
||||
target, start, alternatives,
|
||||
|k| matches!(k, Ref(_, Mutability::Mut)),
|
||||
|k| always_pat!(k, Ref(p, _) => p),
|
||||
|k| always_pat!(k, Ref(p, _) => *p),
|
||||
),
|
||||
// Transform `b @ p0 | ... b @ p1` into `b @ (p0 | p1)`.
|
||||
Ident(b1, i1, Some(target)) => extend_with_matching(
|
||||
target, start, alternatives,
|
||||
// Binding names must match.
|
||||
|k| matches!(k, Ident(b2, i2, Some(_)) if b1 == b2 && eq_id(*i1, *i2)),
|
||||
|k| always_pat!(k, Ident(_, _, Some(p)) => p),
|
||||
|k| always_pat!(k, Ident(_, _, Some(p)) => *p),
|
||||
),
|
||||
// Transform `[pre, x, post] | ... | [pre, y, post]` into `[pre, x | y, post]`.
|
||||
Slice(ps1) => extend_with_matching_product(
|
||||
|
|
@ -309,7 +309,7 @@ fn extend_with_struct_pat(
|
|||
fps1: &mut [ast::PatField],
|
||||
rest1: ast::PatFieldsRest,
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
alternatives: &mut ThinVec<Pat>,
|
||||
) -> bool {
|
||||
(0..fps1.len()).any(|idx| {
|
||||
let pos_in_2 = Cell::new(None); // The element `k`.
|
||||
|
|
@ -339,7 +339,7 @@ fn extend_with_struct_pat(
|
|||
}))
|
||||
},
|
||||
// Extract `p2_k`.
|
||||
|k| always_pat!(k, Struct(_, _, mut fps, _) => fps.swap_remove(pos_in_2.take().unwrap()).pat),
|
||||
|k| always_pat!(k, Struct(_, _, mut fps, _) => *fps.swap_remove(pos_in_2.take().unwrap()).pat),
|
||||
);
|
||||
extend_with_tail_or(&mut fps1[idx].pat, tail_or)
|
||||
})
|
||||
|
|
@ -351,11 +351,11 @@ fn extend_with_struct_pat(
|
|||
/// while also requiring `ps1[..n] ~ ps2[..n]` (pre) and `ps1[n + 1..] ~ ps2[n + 1..]` (post),
|
||||
/// where `~` denotes semantic equality.
|
||||
fn extend_with_matching_product(
|
||||
targets: &mut [Box<Pat>],
|
||||
targets: &mut [Pat],
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
predicate: impl Fn(&PatKind, &[Box<Pat>], usize) -> bool,
|
||||
extract: impl Fn(PatKind) -> ThinVec<Box<Pat>>,
|
||||
alternatives: &mut ThinVec<Pat>,
|
||||
predicate: impl Fn(&PatKind, &[Pat], usize) -> bool,
|
||||
extract: impl Fn(PatKind) -> ThinVec<Pat>,
|
||||
) -> bool {
|
||||
(0..targets.len()).any(|idx| {
|
||||
let tail_or = drain_matching(
|
||||
|
|
@ -382,14 +382,14 @@ fn take_pat(from: &mut Pat) -> Pat {
|
|||
|
||||
/// Extend `target` as an or-pattern with the alternatives
|
||||
/// in `tail_or` if there are any and return if there were.
|
||||
fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<Box<Pat>>) -> bool {
|
||||
fn extend(target: &mut Pat, mut tail_or: ThinVec<Box<Pat>>) {
|
||||
fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<Pat>) -> bool {
|
||||
fn extend(target: &mut Pat, mut tail_or: ThinVec<Pat>) {
|
||||
match target {
|
||||
// On an existing or-pattern in the target, append to it.
|
||||
Pat { kind: Or(ps), .. } => ps.append(&mut tail_or),
|
||||
// Otherwise convert the target to an or-pattern.
|
||||
target => {
|
||||
let mut init_or = thin_vec![Box::new(take_pat(target))];
|
||||
let mut init_or = thin_vec![take_pat(target)];
|
||||
init_or.append(&mut tail_or);
|
||||
target.kind = Or(init_or);
|
||||
},
|
||||
|
|
@ -408,10 +408,10 @@ fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<Box<Pat>>) -> bool {
|
|||
// Only elements beginning with `start` are considered for extraction.
|
||||
fn drain_matching(
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
alternatives: &mut ThinVec<Pat>,
|
||||
predicate: impl Fn(&PatKind) -> bool,
|
||||
extract: impl Fn(PatKind) -> Box<Pat>,
|
||||
) -> ThinVec<Box<Pat>> {
|
||||
extract: impl Fn(PatKind) -> Pat,
|
||||
) -> ThinVec<Pat> {
|
||||
let mut tail_or = ThinVec::new();
|
||||
let mut idx = 0;
|
||||
|
||||
|
|
@ -443,15 +443,15 @@ fn drain_matching(
|
|||
fn extend_with_matching(
|
||||
target: &mut Pat,
|
||||
start: usize,
|
||||
alternatives: &mut ThinVec<Box<Pat>>,
|
||||
alternatives: &mut ThinVec<Pat>,
|
||||
predicate: impl Fn(&PatKind) -> bool,
|
||||
extract: impl Fn(PatKind) -> Box<Pat>,
|
||||
extract: impl Fn(PatKind) -> Pat,
|
||||
) -> bool {
|
||||
extend_with_tail_or(target, drain_matching(start, alternatives, predicate, extract))
|
||||
}
|
||||
|
||||
/// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`?
|
||||
fn eq_pre_post(ps1: &[Box<Pat>], ps2: &[Box<Pat>], idx: usize) -> bool {
|
||||
fn eq_pre_post(ps1: &[Pat], ps2: &[Pat], idx: usize) -> bool {
|
||||
ps1.len() == ps2.len()
|
||||
&& ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`.
|
||||
&& over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r))
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
|||
Pat,
|
||||
NonterminalKind::Pat(PatParam { inferred: false }),
|
||||
|parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
|
||||
|x: Box<ast::Pat>| Some(x)
|
||||
|x: ast::Pat| Some(Box::new(x))
|
||||
);
|
||||
// `parse_item` returns `Option<Box<ast::Item>>`.
|
||||
parse_macro_arg!(
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ impl Rewrite for PatField {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum TuplePatField<'a> {
|
||||
Pat(&'a Box<ast::Pat>),
|
||||
Pat(&'a ast::Pat),
|
||||
Dotdot(Span),
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +561,7 @@ pub(crate) fn can_be_overflowed_pat(
|
|||
}
|
||||
|
||||
fn rewrite_tuple_pat(
|
||||
pats: &[Box<ast::Pat>],
|
||||
pats: &[ast::Pat],
|
||||
path_str: Option<String>,
|
||||
span: Span,
|
||||
context: &RewriteContext<'_>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue