2024-07-16 14:12:24 +00:00
use super ::{ ForceCollect , Parser , PathStyle , Restrictions , Trailing } ;
2023-01-28 21:16:50 +00:00
use crate ::errors ::{
2023-04-27 00:53:06 +00:00
self , AmbiguousRangePattern , DotDotDotForRemainingFields , DotDotDotRangeToPatternNotAllowed ,
2022-10-14 21:16:25 +00:00
DotDotDotRestPattern , EnumPatternInsteadOfIdentifier , ExpectedBindingLeftOfAt ,
2023-08-03 08:56:31 +00:00
ExpectedCommaAfterPatternField , GenericArgsInPatRequireTurbofishSyntax ,
InclusiveRangeExtraEquals , InclusiveRangeMatchArrow , InclusiveRangeNoEnd , InvalidMutInPattern ,
2024-07-06 03:07:46 +00:00
ParenRangeSuggestion , PatternOnWrongSideOfAt , RemoveLet , RepeatedMutInPattern ,
SwitchRefBoxOrder , TopLevelOrPatternNotAllowed , TopLevelOrPatternNotAllowedSugg ,
TrailingVertNotAllowed , UnexpectedExpressionInPattern , UnexpectedLifetimeInPattern ,
UnexpectedParenInRangePat , UnexpectedParenInRangePatSugg ,
UnexpectedVertVertBeforeFunctionParam , UnexpectedVertVertInPattern , WrapInParens ,
2023-01-28 21:16:50 +00:00
} ;
2024-06-18 10:21:05 +00:00
use crate ::parser ::expr ::{ could_be_unclosed_char_literal , LhsExpr } ;
2019-08-11 13:24:37 +00:00
use crate ::{ maybe_recover_from_interpolated_ty_qpath , maybe_whole } ;
2024-07-10 08:17:13 +00:00
use rustc_ast ::mut_visit ::{ walk_pat , MutVisitor } ;
2020-02-29 17:37:32 +00:00
use rustc_ast ::ptr ::P ;
2024-01-28 15:12:21 +00:00
use rustc_ast ::token ::{ self , BinOpToken , Delimiter , Token } ;
2021-07-15 15:36:19 +00:00
use rustc_ast ::{
2024-04-16 23:23:30 +00:00
self as ast , AttrVec , BindingMode , ByRef , Expr , ExprKind , MacCall , Mutability , Pat , PatField ,
PatFieldsRest , PatKind , Path , QSelf , RangeEnd , RangeSyntax ,
2021-07-15 15:36:19 +00:00
} ;
2020-01-11 16:02:46 +00:00
use rustc_ast_pretty ::pprust ;
2024-02-22 23:20:45 +00:00
use rustc_errors ::{ Applicability , Diag , PResult } ;
2022-09-30 01:38:15 +00:00
use rustc_session ::errors ::ExprParenthesesNeeded ;
2023-11-02 03:10:12 +00:00
use rustc_span ::source_map ::{ respan , Spanned } ;
2020-04-19 11:00:18 +00:00
use rustc_span ::symbol ::{ kw , sym , Ident } ;
2024-07-06 03:07:46 +00:00
use rustc_span ::{ BytePos , ErrorGuaranteed , Span } ;
2023-01-30 03:58:23 +00:00
use thin_vec ::{ thin_vec , ThinVec } ;
2019-08-11 13:24:37 +00:00
2022-11-08 21:03:17 +00:00
#[ derive(PartialEq, Copy, Clone) ]
pub enum Expected {
ParameterName ,
ArgumentName ,
Identifier ,
BindingPattern ,
}
2019-08-18 13:31:34 +00:00
2022-11-08 21:03:17 +00:00
impl Expected {
// FIXME(#100717): migrate users of this to proper localization
fn to_string_or_fallback ( expected : Option < Expected > ) -> & 'static str {
match expected {
Some ( Expected ::ParameterName ) = > " parameter name " ,
Some ( Expected ::ArgumentName ) = > " argument name " ,
Some ( Expected ::Identifier ) = > " identifier " ,
Some ( Expected ::BindingPattern ) = > " binding pattern " ,
None = > " pattern " ,
}
}
}
2019-08-25 02:39:28 +00:00
2019-09-29 04:21:20 +00:00
const WHILE_PARSING_OR_MSG : & str = " while parsing this or-pattern starting here " ;
2019-08-25 04:15:11 +00:00
/// Whether or not to recover a `,` when parsing or-patterns.
2019-08-24 20:12:19 +00:00
#[ derive(PartialEq, Copy, Clone) ]
2021-02-08 02:40:33 +00:00
pub enum RecoverComma {
2019-08-25 04:15:11 +00:00
Yes ,
No ,
}
2019-08-24 20:12:19 +00:00
2021-07-13 11:18:03 +00:00
/// Whether or not to recover a `:` when parsing patterns that were meant to be paths.
#[ derive(PartialEq, Copy, Clone) ]
pub enum RecoverColon {
Yes ,
No ,
}
2022-01-12 20:43:24 +00:00
/// Whether or not to recover a `a, b` when parsing patterns as `(a, b)` or that *and* `a | b`.
#[ derive(PartialEq, Copy, Clone) ]
pub enum CommaRecoveryMode {
LikelyTuple ,
EitherTupleOrPipe ,
}
2021-02-13 00:04:37 +00:00
/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
/// emitting duplicate diagnostics.
#[ derive(Debug, Clone, Copy) ]
enum EatOrResult {
/// We recovered from a trailing vert.
TrailingVert ,
/// We ate an `|` (or `||` and recovered).
AteOr ,
/// We did not eat anything (i.e. the current token is not `|` or `||`).
None ,
}
2022-10-14 21:16:25 +00:00
/// The syntax location of a given pattern. Used for diagnostics.
2023-08-02 16:00:56 +00:00
#[ derive(Clone, Copy) ]
pub enum PatternLocation {
2022-10-14 21:16:25 +00:00
LetBinding ,
FunctionParameter ,
}
2019-08-11 13:24:37 +00:00
impl < ' a > Parser < ' a > {
/// Parses a pattern.
2019-08-18 20:35:53 +00:00
///
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
/// at the top level. Used when parsing the parameters of lambda expressions,
/// functions, function pointers, and `pat` macro fragments.
2023-08-02 16:00:56 +00:00
pub fn parse_pat_no_top_alt (
& mut self ,
expected : Option < Expected > ,
syntax_loc : Option < PatternLocation > ,
) -> PResult < ' a , P < Pat > > {
self . parse_pat_with_range_pat ( true , expected , syntax_loc )
2019-08-11 13:24:37 +00:00
}
2021-02-08 02:40:33 +00:00
/// Parses a pattern.
///
2019-08-18 20:04:28 +00:00
/// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
2021-02-08 02:40:33 +00:00
/// Used for parsing patterns in all cases when `pat<no_top_alt>` is not used.
///
/// Note that after the FCP in <https://github.com/rust-lang/rust/issues/81415>,
/// a leading vert is allowed in nested or-patterns, too. This allows us to
/// simplify the grammar somewhat.
pub fn parse_pat_allow_top_alt (
2020-11-11 00:00:53 +00:00
& mut self ,
2022-11-08 21:03:17 +00:00
expected : Option < Expected > ,
2020-11-11 00:00:53 +00:00
rc : RecoverComma ,
2021-07-13 11:18:03 +00:00
ra : RecoverColon ,
2022-01-12 20:43:24 +00:00
rt : CommaRecoveryMode ,
2020-11-11 00:00:53 +00:00
) -> PResult < ' a , P < Pat > > {
2023-08-02 16:00:56 +00:00
self . parse_pat_allow_top_alt_inner ( expected , rc , ra , rt , None ) . map ( | ( pat , _ ) | pat )
2021-02-13 00:04:37 +00:00
}
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
/// recovered).
fn parse_pat_allow_top_alt_inner (
& mut self ,
2022-11-08 21:03:17 +00:00
expected : Option < Expected > ,
2021-02-13 00:04:37 +00:00
rc : RecoverComma ,
2021-07-13 11:18:03 +00:00
ra : RecoverColon ,
2022-01-12 20:43:24 +00:00
rt : CommaRecoveryMode ,
2023-08-02 16:00:56 +00:00
syntax_loc : Option < PatternLocation > ,
2021-02-13 00:04:37 +00:00
) -> PResult < ' a , ( P < Pat > , bool ) > {
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
// suggestions (which bothers rustfix).
//
2019-08-18 20:04:28 +00:00
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
2021-02-13 00:04:37 +00:00
let ( leading_vert_span , mut trailing_vert ) = match self . eat_or_separator ( None ) {
EatOrResult ::AteOr = > ( Some ( self . prev_token . span ) , false ) ,
EatOrResult ::TrailingVert = > ( None , true ) ,
EatOrResult ::None = > ( None , false ) ,
} ;
2019-08-18 13:28:14 +00:00
2019-09-29 04:21:20 +00:00
// Parse the first pattern (`p_0`).
2023-11-06 21:06:20 +00:00
let mut first_pat = match self . parse_pat_no_top_alt ( expected , syntax_loc ) {
Ok ( pat ) = > pat ,
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
Err ( err )
2023-11-06 21:06:20 +00:00
if self . token . is_reserved_ident ( )
& & ! self . token . is_keyword ( kw ::In )
& & ! self . token . is_keyword ( kw ::If ) = >
{
err . emit ( ) ;
self . bump ( ) ;
self . mk_pat ( self . token . span , PatKind ::Wild )
}
Err ( err ) = > return Err ( err ) ,
} ;
2023-11-27 02:15:56 +00:00
if rc = = RecoverComma ::Yes & & ! first_pat . could_be_never_pattern ( ) {
2023-11-26 23:50:51 +00:00
self . maybe_recover_unexpected_comma ( first_pat . span , rt ) ? ;
2022-05-19 06:07:55 +00:00
}
2019-07-14 01:05:52 +00:00
2019-08-18 13:45:44 +00:00
// If the next token is not a `|`,
// this is not an or-pattern and we should exit here.
2019-08-18 14:35:19 +00:00
if ! self . check ( & token ::BinOp ( token ::Or ) ) & & self . token ! = token ::OrOr {
2021-02-08 02:40:33 +00:00
// If we parsed a leading `|` which should be gated,
// then we should really gate the leading `|`.
// This complicated procedure is done purely for diagnostics UX.
2021-07-13 11:18:03 +00:00
2021-11-21 04:56:32 +00:00
// Check if the user wrote `foo:bar` instead of `foo::bar`.
2022-05-19 06:04:35 +00:00
if ra = = RecoverColon ::Yes {
2023-01-30 18:08:50 +00:00
first_pat = self . maybe_recover_colon_colon_in_pat_typo ( first_pat , expected ) ;
2022-05-19 06:04:35 +00:00
}
2021-07-13 11:18:03 +00:00
2021-02-08 02:40:33 +00:00
if let Some ( leading_vert_span ) = leading_vert_span {
// If there was a leading vert, treat this as an or-pattern. This improves
// diagnostics.
let span = leading_vert_span . to ( self . prev_token . span ) ;
2022-11-23 00:55:16 +00:00
return Ok ( ( self . mk_pat ( span , PatKind ::Or ( thin_vec! [ first_pat ] ) ) , trailing_vert ) ) ;
2021-02-08 02:40:33 +00:00
}
2021-02-13 00:04:37 +00:00
return Ok ( ( first_pat , trailing_vert ) ) ;
2019-07-14 01:05:52 +00:00
}
2019-09-29 04:21:20 +00:00
// Parse the patterns `p_1 | ... | p_n` where `n > 0`.
2021-02-08 02:40:33 +00:00
let lo = leading_vert_span . unwrap_or ( first_pat . span ) ;
2022-11-23 00:55:16 +00:00
let mut pats = thin_vec! [ first_pat ] ;
2021-02-13 00:04:37 +00:00
loop {
match self . eat_or_separator ( Some ( lo ) ) {
EatOrResult ::AteOr = > { }
EatOrResult ::None = > break ,
EatOrResult ::TrailingVert = > {
trailing_vert = true ;
break ;
}
}
2023-08-02 16:00:56 +00:00
let pat = self . parse_pat_no_top_alt ( expected , syntax_loc ) . map_err ( | mut err | {
2019-09-29 04:21:20 +00:00
err . span_label ( lo , WHILE_PARSING_OR_MSG ) ;
2019-08-24 23:50:21 +00:00
err
} ) ? ;
2023-11-27 02:15:56 +00:00
if rc = = RecoverComma ::Yes & & ! pat . could_be_never_pattern ( ) {
2023-11-26 23:50:51 +00:00
self . maybe_recover_unexpected_comma ( pat . span , rt ) ? ;
2022-05-19 06:07:55 +00:00
}
2019-08-18 15:44:27 +00:00
pats . push ( pat ) ;
2019-07-14 01:05:52 +00:00
}
2020-02-29 11:56:15 +00:00
let or_pattern_span = lo . to ( self . prev_token . span ) ;
2019-07-14 01:05:52 +00:00
2021-02-13 00:04:37 +00:00
Ok ( ( self . mk_pat ( or_pattern_span , PatKind ::Or ( pats ) ) , trailing_vert ) )
2019-07-14 01:05:52 +00:00
}
2021-02-13 00:04:37 +00:00
/// Parse a pattern and (maybe) a `Colon` in positions where a pattern may be followed by a
/// type annotation (e.g. for `let` bindings or `fn` params).
///
/// Generally, this corresponds to `pat_no_top_alt` followed by an optional `Colon`. It will
/// eat the `Colon` token if one is present.
///
/// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
/// otherwise).
pub ( super ) fn parse_pat_before_ty (
& mut self ,
2022-11-08 21:03:17 +00:00
expected : Option < Expected > ,
2021-02-13 00:04:37 +00:00
rc : RecoverComma ,
2022-10-14 21:16:25 +00:00
syntax_loc : PatternLocation ,
2021-02-13 00:04:37 +00:00
) -> PResult < ' a , ( P < Pat > , bool ) > {
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
// or-patterns so that we can detect when a user tries to use it. This allows us to print a
// better error message.
2022-01-12 20:43:24 +00:00
let ( pat , trailing_vert ) = self . parse_pat_allow_top_alt_inner (
expected ,
rc ,
RecoverColon ::No ,
CommaRecoveryMode ::LikelyTuple ,
2023-08-02 16:00:56 +00:00
Some ( syntax_loc ) ,
2022-01-12 20:43:24 +00:00
) ? ;
2021-02-13 00:04:37 +00:00
let colon = self . eat ( & token ::Colon ) ;
if let PatKind ::Or ( pats ) = & pat . kind {
2022-10-14 21:16:25 +00:00
let span = pat . span ;
2023-07-20 09:51:47 +00:00
let sub = if pats . len ( ) = = 1 {
2024-07-06 03:07:46 +00:00
Some ( TopLevelOrPatternNotAllowedSugg ::RemoveLeadingVert {
span : span . with_hi ( span . lo ( ) + BytePos ( 1 ) ) ,
} )
2021-02-13 00:04:37 +00:00
} else {
2024-07-06 03:07:46 +00:00
Some ( TopLevelOrPatternNotAllowedSugg ::WrapInParens {
span ,
suggestion : WrapInParens { lo : span . shrink_to_lo ( ) , hi : span . shrink_to_hi ( ) } ,
} )
2023-07-20 09:51:47 +00:00
} ;
2022-10-14 21:16:25 +00:00
2024-01-05 05:38:04 +00:00
let err = self . dcx ( ) . create_err ( match syntax_loc {
2023-07-20 09:51:47 +00:00
PatternLocation ::LetBinding = > {
TopLevelOrPatternNotAllowed ::LetBinding { span , sub }
}
PatternLocation ::FunctionParameter = > {
TopLevelOrPatternNotAllowed ::FunctionParameter { span , sub }
}
} ) ;
if trailing_vert {
2024-01-05 05:38:04 +00:00
err . delay_as_bug ( ) ;
} else {
err . emit ( ) ;
2021-02-13 00:04:37 +00:00
}
}
Ok ( ( pat , colon ) )
}
/// Parse the pattern for a function or function pointer parameter, followed by a colon.
///
/// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
/// otherwise).
pub ( super ) fn parse_fn_param_pat_colon ( & mut self ) -> PResult < ' a , ( P < Pat > , bool ) > {
2021-02-08 02:40:33 +00:00
// In order to get good UX, we first recover in the case of a leading vert for an illegal
// top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
// a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
// separately.
if let token ::OrOr = self . token . kind {
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( UnexpectedVertVertBeforeFunctionParam { span : self . token . span } ) ;
2021-02-08 02:40:33 +00:00
self . bump ( ) ;
}
2022-10-14 21:16:25 +00:00
self . parse_pat_before_ty (
2022-11-08 21:03:17 +00:00
Some ( Expected ::ParameterName ) ,
2022-10-14 21:16:25 +00:00
RecoverComma ::No ,
PatternLocation ::FunctionParameter ,
)
2021-02-08 02:40:33 +00:00
}
2019-08-18 16:13:19 +00:00
/// Eat the or-pattern `|` separator.
/// If instead a `||` token is encountered, recover and pretend we parsed `|`.
2021-02-13 00:04:37 +00:00
fn eat_or_separator ( & mut self , lo : Option < Span > ) -> EatOrResult {
2019-09-29 04:21:20 +00:00
if self . recover_trailing_vert ( lo ) {
2021-02-13 00:04:37 +00:00
EatOrResult ::TrailingVert
} else if matches! ( self . token . kind , token ::OrOr ) {
// Found `||`; Recover and pretend we parsed `|`.
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( UnexpectedVertVertInPattern { span : self . token . span , start : lo } ) ;
2021-02-13 00:04:37 +00:00
self . bump ( ) ;
EatOrResult ::AteOr
} else if self . eat ( & token ::BinOp ( token ::Or ) ) {
EatOrResult ::AteOr
} else {
EatOrResult ::None
2019-08-18 16:13:19 +00:00
}
}
2019-09-29 04:21:20 +00:00
/// Recover if `|` or `||` is the current token and we have one of the
/// tokens `=>`, `if`, `=`, `:`, `;`, `,`, `]`, `)`, or `}` ahead of us.
///
/// These tokens all indicate that we reached the end of the or-pattern
/// list and can now reliably say that the `|` was an illegal trailing vert.
/// Note that there are more tokens such as `@` for which we know that the `|`
/// is an illegal parse. However, the user's intent is less clear in that case.
fn recover_trailing_vert ( & mut self , lo : Option < Span > ) -> bool {
2020-10-27 01:02:48 +00:00
let is_end_ahead = self . look_ahead ( 1 , | token | {
matches! (
& token . uninterpolate ( ) . kind ,
token ::FatArrow // e.g. `a | => 0,`.
2024-02-13 23:28:27 +00:00
| token ::Ident ( kw ::If , token ::IdentIsRaw ::No ) // e.g. `a | if expr`.
2021-02-13 00:04:37 +00:00
| token ::Eq // e.g. `let a | = 0`.
| token ::Semi // e.g. `let a |;`.
| token ::Colon // e.g. `let a | :`.
| token ::Comma // e.g. `let (a |,)`.
2022-04-26 12:40:14 +00:00
| token ::CloseDelim ( Delimiter ::Bracket ) // e.g. `let [a | ]`.
| token ::CloseDelim ( Delimiter ::Parenthesis ) // e.g. `let (a | )`.
| token ::CloseDelim ( Delimiter ::Brace ) // e.g. `let A { f: a | }`.
2020-10-27 01:02:48 +00:00
)
2019-09-29 04:21:20 +00:00
} ) ;
match ( is_end_ahead , & self . token . kind ) {
2020-04-17 00:38:52 +00:00
( true , token ::BinOp ( token ::Or ) | token ::OrOr ) = > {
2022-10-14 21:16:25 +00:00
// A `|` or possibly `||` token shouldn't be here. Ban it.
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( TrailingVertNotAllowed {
2022-10-14 21:16:25 +00:00
span : self . token . span ,
start : lo ,
token : self . token . clone ( ) ,
note_double_vert : matches ! ( self . token . kind , token ::OrOr ) . then_some ( ( ) ) ,
} ) ;
2019-09-29 04:21:20 +00:00
self . bump ( ) ;
true
}
_ = > false ,
}
}
2024-01-28 15:12:21 +00:00
/// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
///
/// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end))
/// in order to say "expected a pattern range bound" instead of "expected a pattern";
/// ```text
/// 0..=1 + 2
/// ^^^^^
/// ```
/// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
#[ must_use = " the pattern must be discarded as `PatKind::Err` if this function returns Some " ]
fn maybe_recover_trailing_expr (
& mut self ,
pat_span : Span ,
is_end_bound : bool ,
) -> Option < ErrorGuaranteed > {
if self . prev_token . is_keyword ( kw ::Underscore ) | | ! self . may_recover ( ) {
// Don't recover anything after an `_` or if recovery is disabled.
return None ;
}
// Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`.
let has_trailing_method = self . check_noexpect ( & token ::Dot )
& & self . look_ahead ( 1 , | tok | {
tok . ident ( )
. and_then ( | ( ident , _ ) | ident . name . as_str ( ) . chars ( ) . next ( ) )
. is_some_and ( char ::is_lowercase )
} )
& & self . look_ahead ( 2 , | tok | tok . kind = = token ::OpenDelim ( Delimiter ::Parenthesis ) ) ;
// Check for operators.
// `|` is excluded as it is used in pattern alternatives and lambdas,
// `?` is included for error propagation,
// `[` is included for indexing operations,
// `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`)
let has_trailing_operator = matches! ( self . token . kind , token ::BinOp ( op ) if op ! = BinOpToken ::Or )
| | self . token . kind = = token ::Question
| | ( self . token . kind = = token ::OpenDelim ( Delimiter ::Bracket )
& & self . look_ahead ( 1 , | tok | tok . kind ! = token ::CloseDelim ( Delimiter ::Bracket ) ) ) ;
if ! has_trailing_method & & ! has_trailing_operator {
// Nothing to recover here.
return None ;
}
// Let's try to parse an expression to emit a better diagnostic.
let mut snapshot = self . create_snapshot_for_diagnostic ( ) ;
snapshot . restrictions . insert ( Restrictions ::IS_PAT ) ;
// Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
if let Ok ( expr ) = snapshot
. parse_expr_dot_or_call_with (
2024-07-16 05:54:34 +00:00
AttrVec ::new ( ) ,
2024-02-25 21:22:09 +00:00
self . mk_expr ( pat_span , ExprKind ::Dummy ) , // equivalent to transforming the parsed pattern into an `Expr`
2024-01-28 15:12:21 +00:00
pat_span ,
)
. map_err ( | err | err . cancel ( ) )
{
let non_assoc_span = expr . span ;
// Parse an associative expression such as `+ expr`, `% expr`, ...
// Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
2024-06-18 10:40:27 +00:00
let lhs = LhsExpr ::Parsed { expr , starts_statement : false } ;
2024-06-18 10:21:05 +00:00
if let Ok ( expr ) = snapshot . parse_expr_assoc_with ( 0 , lhs ) . map_err ( | err | err . cancel ( ) ) {
2024-01-28 15:12:21 +00:00
// We got a valid expression.
self . restore_snapshot ( snapshot ) ;
self . restrictions . remove ( Restrictions ::IS_PAT ) ;
let is_bound = is_end_bound
// is_start_bound: either `..` or `)..`
| | self . token . is_range_separator ( )
| | self . token . kind = = token ::CloseDelim ( Delimiter ::Parenthesis )
& & self . look_ahead ( 1 , Token ::is_range_separator ) ;
// Check that `parse_expr_assoc_with` didn't eat a rhs.
let is_method_call = has_trailing_method & & non_assoc_span = = expr . span ;
return Some ( self . dcx ( ) . emit_err ( UnexpectedExpressionInPattern {
span : expr . span ,
is_bound ,
is_method_call ,
} ) ) ;
}
}
// We got a trailing method/operator, but we couldn't parse an expression.
None
}
2019-08-11 13:24:37 +00:00
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
/// allowed).
fn parse_pat_with_range_pat (
& mut self ,
allow_range_pat : bool ,
2022-11-08 21:03:17 +00:00
expected : Option < Expected > ,
2023-08-02 16:00:56 +00:00
syntax_loc : Option < PatternLocation > ,
2019-08-11 13:24:37 +00:00
) -> PResult < ' a , P < Pat > > {
maybe_recover_from_interpolated_ty_qpath! ( self , true ) ;
2024-03-19 20:18:38 +00:00
maybe_whole! ( self , NtPat , | pat | pat ) ;
2019-08-11 13:24:37 +00:00
2022-09-03 05:39:46 +00:00
let mut lo = self . token . span ;
if self . token . is_keyword ( kw ::Let ) & & self . look_ahead ( 1 , | tok | tok . can_begin_pattern ( ) ) {
self . bump ( ) ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( RemoveLet { span : lo } ) ;
2022-09-03 05:39:46 +00:00
lo = self . token . span ;
}
2019-12-11 09:04:34 +00:00
let pat = if self . check ( & token ::BinOp ( token ::And ) ) | | self . token . kind = = token ::AndAnd {
self . parse_pat_deref ( expected ) ?
2022-04-26 12:40:14 +00:00
} else if self . check ( & token ::OpenDelim ( Delimiter ::Parenthesis ) ) {
2019-12-11 09:04:34 +00:00
self . parse_pat_tuple_or_parens ( ) ?
2022-04-26 12:40:14 +00:00
} else if self . check ( & token ::OpenDelim ( Delimiter ::Bracket ) ) {
2019-12-11 09:04:34 +00:00
// Parse `[pat, pat,...]` as a slice pattern.
2022-04-26 12:40:14 +00:00
let ( pats , _ ) = self . parse_delim_comma_seq ( Delimiter ::Bracket , | p | {
2022-01-12 20:43:24 +00:00
p . parse_pat_allow_top_alt (
None ,
RecoverComma ::No ,
RecoverColon ::No ,
CommaRecoveryMode ::EitherTupleOrPipe ,
)
2021-02-08 02:40:33 +00:00
} ) ? ;
2019-12-11 09:04:34 +00:00
PatKind ::Slice ( pats )
} else if self . check ( & token ::DotDot ) & & ! self . is_pat_range_end_start ( 1 ) {
// A rest pattern `..`.
self . bump ( ) ; // `..`
PatKind ::Rest
2020-03-26 05:06:52 +00:00
} else if self . check ( & token ::DotDotDot ) & & ! self . is_pat_range_end_start ( 1 ) {
self . recover_dotdotdot_rest_pat ( lo )
2019-12-11 09:04:34 +00:00
} else if let Some ( form ) = self . parse_range_end ( ) {
self . parse_pat_range_to ( form ) ? // `..=X`, `...X`, or `..X`.
2023-11-22 01:30:43 +00:00
} else if self . eat ( & token ::Not ) {
// Parse `!`
2024-03-04 05:31:49 +00:00
self . psess . gated_spans . gate ( sym ::never_patterns , self . prev_token . span ) ;
2023-11-22 01:30:43 +00:00
PatKind ::Never
2019-12-11 09:04:34 +00:00
} else if self . eat_keyword ( kw ::Underscore ) {
2023-11-22 01:30:43 +00:00
// Parse `_`
2019-12-11 09:04:34 +00:00
PatKind ::Wild
} else if self . eat_keyword ( kw ::Mut ) {
2024-03-24 01:04:45 +00:00
self . parse_pat_ident_mut ( ) ?
2019-12-11 09:04:34 +00:00
} else if self . eat_keyword ( kw ::Ref ) {
2023-11-27 09:28:51 +00:00
if self . check_keyword ( kw ::Box ) {
2023-11-29 18:45:36 +00:00
// Suggest `box ref`.
2023-11-27 09:28:51 +00:00
let span = self . prev_token . span . to ( self . token . span ) ;
2023-11-29 18:45:36 +00:00
self . bump ( ) ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( SwitchRefBoxOrder { span } ) ;
2023-11-27 09:28:51 +00:00
}
2019-12-11 09:04:34 +00:00
// Parse ref ident @ pat / ref mut ident @ pat
let mutbl = self . parse_mutability ( ) ;
2024-04-16 23:23:30 +00:00
self . parse_pat_ident ( BindingMode ( ByRef ::Yes ( mutbl ) , Mutability ::Not ) , syntax_loc ) ?
2019-12-11 09:04:34 +00:00
} else if self . eat_keyword ( kw ::Box ) {
2022-06-08 04:40:55 +00:00
self . parse_pat_box ( ) ?
2020-10-19 21:44:37 +00:00
} else if self . check_inline_const ( 0 ) {
2020-09-23 21:34:44 +00:00
// Parse `const pat`
2021-11-22 16:25:28 +00:00
let const_expr = self . parse_const_block ( lo . to ( self . token . span ) , true ) ? ;
2020-10-19 19:18:47 +00:00
if let Some ( re ) = self . parse_range_end ( ) {
self . parse_pat_range_begin_with ( const_expr , re ) ?
} else {
PatKind ::Lit ( const_expr )
}
2024-03-20 20:53:50 +00:00
} else if self . is_builtin ( ) {
self . parse_pat_builtin ( ) ?
}
2023-03-17 09:27:17 +00:00
// Don't eagerly error on semantically invalid tokens when matching
// declarative macros, as the input to those doesn't have to be
// semantically valid. For attribute/derive proc macros this is not the
// case, so doing the recovery for them is fine.
2024-03-20 20:53:50 +00:00
else if self . can_be_ident_pat ( )
2023-03-17 09:27:17 +00:00
| | ( self . is_lit_bad_ident ( ) . is_some ( ) & & self . may_recover ( ) )
{
2019-12-11 09:04:34 +00:00
// Parse `ident @ pat`
// This can give false positives and parse nullary enums,
// they are dealt with later in resolve.
2024-04-16 23:23:30 +00:00
self . parse_pat_ident ( BindingMode ::NONE , syntax_loc ) ?
2019-12-11 09:04:34 +00:00
} else if self . is_start_of_pat_with_path ( ) {
// Parse pattern starting with a path
let ( qself , path ) = if self . eat_lt ( ) {
// Parse a qualified path
2022-11-16 20:46:06 +00:00
let ( qself , path ) = self . parse_qpath ( PathStyle ::Pat ) ? ;
2019-12-11 09:04:34 +00:00
( Some ( qself ) , path )
} else {
// Parse an unqualified path
2022-11-16 20:46:06 +00:00
( None , self . parse_path ( PathStyle ::Pat ) ? )
2019-12-11 09:04:34 +00:00
} ;
2020-02-29 11:56:15 +00:00
let span = lo . to ( self . prev_token . span ) ;
2019-12-11 09:04:34 +00:00
if qself . is_none ( ) & & self . check ( & token ::Not ) {
self . parse_pat_mac_invoc ( path ) ?
} else if let Some ( form ) = self . parse_range_end ( ) {
2022-08-14 23:58:38 +00:00
let begin = self . mk_expr ( span , ExprKind ::Path ( qself , path ) ) ;
2019-12-11 09:04:34 +00:00
self . parse_pat_range_begin_with ( begin , form ) ?
2022-04-26 12:40:14 +00:00
} else if self . check ( & token ::OpenDelim ( Delimiter ::Brace ) ) {
2019-12-11 09:04:34 +00:00
self . parse_pat_struct ( qself , path ) ?
2022-04-26 12:40:14 +00:00
} else if self . check ( & token ::OpenDelim ( Delimiter ::Parenthesis ) ) {
2019-12-11 09:04:34 +00:00
self . parse_pat_tuple_struct ( qself , path ) ?
} else {
2024-01-28 15:12:21 +00:00
match self . maybe_recover_trailing_expr ( span , false ) {
Some ( guar ) = > PatKind ::Err ( guar ) ,
None = > PatKind ::Path ( qself , path ) ,
}
2019-08-11 13:24:37 +00:00
}
2024-06-20 20:36:35 +00:00
} else if let Some ( lt ) = self . token . lifetime ( )
2022-09-01 18:48:09 +00:00
// In pattern position, we're totally fine with using "next token isn't colon"
// as a heuristic. We could probably just always try to recover if it's a lifetime,
// because we never have `'a: label {}` in a pattern position anyways, but it does
// keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
2024-06-20 20:36:35 +00:00
& & could_be_unclosed_char_literal ( lt )
2022-09-01 18:48:09 +00:00
& & ! self . look_ahead ( 1 , | token | matches! ( token . kind , token ::Colon ) )
{
// Recover a `'a` as a `'a'` literal
let lt = self . expect_lifetime ( ) ;
2022-12-05 03:39:56 +00:00
let ( lit , _ ) =
self . recover_unclosed_char ( lt . ident , Parser ::mk_token_lit_char , | self_ | {
2022-11-08 21:03:17 +00:00
let expected = Expected ::to_string_or_fallback ( expected ) ;
2022-12-05 03:39:56 +00:00
let msg = format! (
" expected {}, found {} " ,
expected ,
super ::token_descr ( & self_ . token )
) ;
2024-01-03 05:00:29 +00:00
self_
. dcx ( )
. struct_span_err ( self_ . token . span , msg )
2024-01-08 22:08:49 +00:00
. with_span_label ( self_ . token . span , format! ( " expected {expected} " ) )
2022-12-05 03:39:56 +00:00
} ) ;
PatKind ::Lit ( self . mk_expr ( lo , ExprKind ::Lit ( lit ) ) )
2019-12-11 09:04:34 +00:00
} else {
// Try to parse everything else as literal with optional minus
match self . parse_literal_maybe_minus ( ) {
2024-01-28 15:12:21 +00:00
Ok ( begin ) = > {
let begin = match self . maybe_recover_trailing_expr ( begin . span , false ) {
2024-02-25 21:22:11 +00:00
Some ( guar ) = > self . mk_expr_err ( begin . span , guar ) ,
2024-01-28 15:12:21 +00:00
None = > begin ,
} ;
match self . parse_range_end ( ) {
Some ( form ) = > self . parse_pat_range_begin_with ( begin , form ) ? ,
None = > PatKind ::Lit ( begin ) ,
}
}
2019-12-11 09:04:34 +00:00
Err ( err ) = > return self . fatal_unexpected_non_pat ( err , expected ) ,
2019-08-11 13:24:37 +00:00
}
2019-08-12 05:34:08 +00:00
} ;
2019-08-11 13:24:37 +00:00
2020-02-29 11:56:15 +00:00
let pat = self . mk_pat ( lo . to ( self . prev_token . span ) , pat ) ;
2022-05-19 05:51:49 +00:00
let pat = self . maybe_recover_from_bad_qpath ( pat ) ? ;
2019-10-14 14:47:12 +00:00
let pat = self . recover_intersection_pat ( pat ) ? ;
2019-08-11 13:24:37 +00:00
if ! allow_range_pat {
2019-12-11 09:04:34 +00:00
self . ban_pat_range_if_ambiguous ( & pat )
2019-08-11 13:24:37 +00:00
}
Ok ( pat )
}
2020-03-26 05:06:52 +00:00
/// Recover from a typoed `...` pattern that was encountered
/// Ref: Issue #70388
fn recover_dotdotdot_rest_pat ( & mut self , lo : Span ) -> PatKind {
// A typoed rest pattern `...`.
self . bump ( ) ; // `...`
// The user probably mistook `...` for a rest pattern `..`.
2024-07-06 03:07:46 +00:00
self . dcx ( ) . emit_err ( DotDotDotRestPattern {
span : lo ,
suggestion : lo . with_lo ( lo . hi ( ) - BytePos ( 1 ) ) ,
} ) ;
2020-03-26 05:06:52 +00:00
PatKind ::Rest
}
2019-10-14 14:47:12 +00:00
/// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
///
/// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs`
2023-01-14 17:23:40 +00:00
/// should already have been parsed by now at this point,
2019-10-14 14:47:12 +00:00
/// if the next token is `@` then we can try to parse the more general form.
///
/// Consult `parse_pat_ident` for the `binding` grammar.
///
/// The notion of intersection patterns are found in
/// 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 : P < Pat > ) -> PResult < ' a , P < Pat > > {
if self . token . kind ! = 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 ( ) ; // `@`
2023-08-02 16:00:56 +00:00
let mut rhs = self . parse_pat_no_top_alt ( None , None ) ? ;
2022-10-14 21:16:25 +00:00
let whole_span = lhs . span . to ( rhs . span ) ;
2019-10-14 14:47:12 +00:00
2022-11-22 09:42:01 +00:00
if let PatKind ::Ident ( _ , _ , sub @ None ) = & mut rhs . kind {
2019-10-14 14:47:12 +00:00
// The user inverted the order, so help them fix that.
let lhs_span = lhs . span ;
// Move the LHS into the RHS as a subpattern.
// The RHS is now the full pattern.
* sub = Some ( lhs ) ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( PatternOnWrongSideOfAt {
2022-10-14 21:16:25 +00:00
whole_span ,
whole_pat : pprust ::pat_to_string ( & rhs ) ,
pattern : lhs_span ,
binding : rhs . span ,
} ) ;
2019-10-14 15:25:50 +00:00
} else {
// The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
rhs . kind = PatKind ::Wild ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( ExpectedBindingLeftOfAt {
2022-10-14 21:16:25 +00:00
whole_span ,
lhs : lhs . span ,
rhs : rhs . span ,
} ) ;
2019-10-14 14:47:12 +00:00
}
2022-10-14 21:16:25 +00:00
rhs . span = whole_span ;
2019-10-14 15:25:50 +00:00
Ok ( rhs )
2019-10-14 14:47:12 +00:00
}
2019-08-12 06:16:04 +00:00
/// Ban a range pattern if it has an ambiguous interpretation.
2019-12-11 09:04:34 +00:00
fn ban_pat_range_if_ambiguous ( & self , pat : & Pat ) {
2019-09-26 15:18:31 +00:00
match pat . kind {
2019-08-12 06:16:04 +00:00
PatKind ::Range (
.. ,
Spanned { node : RangeEnd ::Included ( RangeSyntax ::DotDotDot ) , .. } ,
2019-12-11 09:04:34 +00:00
) = > return ,
2019-08-12 06:16:04 +00:00
PatKind ::Range ( .. ) = > { }
2019-12-11 09:04:34 +00:00
_ = > return ,
2019-08-12 06:16:04 +00:00
}
2024-07-06 03:07:46 +00:00
self . dcx ( ) . emit_err ( AmbiguousRangePattern {
span : pat . span ,
suggestion : ParenRangeSuggestion {
lo : pat . span . shrink_to_lo ( ) ,
hi : pat . span . shrink_to_hi ( ) ,
} ,
} ) ;
2019-08-12 06:16:04 +00:00
}
2019-08-12 05:37:08 +00:00
/// Parse `&pat` / `&mut pat`.
2022-11-08 21:03:17 +00:00
fn parse_pat_deref ( & mut self , expected : Option < Expected > ) -> PResult < ' a , PatKind > {
2019-08-12 05:37:08 +00:00
self . expect_and ( ) ? ;
2024-06-20 20:36:35 +00:00
if let Some ( lifetime ) = self . token . lifetime ( ) {
2019-12-12 23:59:33 +00:00
self . bump ( ) ; // `'a`
2024-07-06 03:07:46 +00:00
self . dcx ( ) . emit_err ( UnexpectedLifetimeInPattern {
span : self . prev_token . span ,
2024-06-20 20:36:35 +00:00
symbol : lifetime . name ,
2024-07-06 03:07:46 +00:00
suggestion : self . prev_token . span . until ( self . token . span ) ,
} ) ;
2019-08-12 05:37:08 +00:00
}
2022-10-14 21:16:25 +00:00
let mutbl = self . parse_mutability ( ) ;
2023-08-02 16:00:56 +00:00
let subpat = self . parse_pat_with_range_pat ( false , expected , None ) ? ;
2022-10-14 21:16:25 +00:00
Ok ( PatKind ::Ref ( subpat , mutbl ) )
2019-08-12 05:37:08 +00:00
}
2019-08-12 05:41:50 +00:00
/// Parse a tuple or parenthesis pattern.
fn parse_pat_tuple_or_parens ( & mut self ) -> PResult < ' a , PatKind > {
2024-01-03 14:27:58 +00:00
let open_paren = self . token . span ;
2021-07-13 11:18:03 +00:00
let ( fields , trailing_comma ) = self . parse_paren_comma_seq ( | p | {
2022-01-12 20:43:24 +00:00
p . parse_pat_allow_top_alt (
None ,
RecoverComma ::No ,
RecoverColon ::No ,
CommaRecoveryMode ::LikelyTuple ,
)
2021-07-13 11:18:03 +00:00
} ) ? ;
2019-08-12 05:41:50 +00:00
// Here, `(pat,)` is a tuple pattern.
// For backward compatibility, `(..)` is a tuple pattern as well.
2024-02-13 23:48:23 +00:00
let paren_pattern =
fields . len ( ) = = 1 & & ! ( matches! ( trailing_comma , Trailing ::Yes ) | | fields [ 0 ] . is_rest ( ) ) ;
if paren_pattern {
2024-01-03 14:27:58 +00:00
let pat = fields . into_iter ( ) . next ( ) . unwrap ( ) ;
let close_paren = self . prev_token . span ;
match & pat . kind {
// recover ranges with parentheses around the `(start)..`
PatKind ::Lit ( begin )
if self . may_recover ( )
& & let Some ( form ) = self . parse_range_end ( ) = >
{
self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
span : vec ! [ open_paren , close_paren ] ,
sugg : UnexpectedParenInRangePatSugg {
start_span : open_paren ,
end_span : close_paren ,
} ,
} ) ;
2024-02-13 23:48:23 +00:00
self . parse_pat_range_begin_with ( begin . clone ( ) , form )
2024-01-03 14:27:58 +00:00
}
2024-01-28 15:12:21 +00:00
// recover ranges with parentheses around the `(start)..`
2024-02-25 21:22:11 +00:00
PatKind ::Err ( guar )
2024-01-28 15:12:21 +00:00
if self . may_recover ( )
& & let Some ( form ) = self . parse_range_end ( ) = >
{
self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
span : vec ! [ open_paren , close_paren ] ,
sugg : UnexpectedParenInRangePatSugg {
start_span : open_paren ,
end_span : close_paren ,
} ,
} ) ;
2024-02-25 21:22:11 +00:00
self . parse_pat_range_begin_with ( self . mk_expr_err ( pat . span , * guar ) , form )
2024-01-28 15:12:21 +00:00
}
2024-01-03 14:27:58 +00:00
// (pat) with optional parentheses
2024-02-13 23:48:23 +00:00
_ = > Ok ( PatKind ::Paren ( pat ) ) ,
2024-01-03 14:27:58 +00:00
}
2019-08-12 05:41:50 +00:00
} else {
2024-02-13 23:48:23 +00:00
Ok ( PatKind ::Tuple ( fields ) )
}
2019-08-12 05:41:50 +00:00
}
2019-08-27 17:51:21 +00:00
/// Parse a mutable binding with the `mut` token already eaten.
2024-03-24 01:04:45 +00:00
fn parse_pat_ident_mut ( & mut self ) -> PResult < ' a , PatKind > {
2020-02-29 11:56:15 +00:00
let mut_span = self . prev_token . span ;
2019-08-27 11:04:48 +00:00
2024-03-24 01:04:45 +00:00
self . recover_additional_muts ( ) ;
let byref = self . parse_byref ( ) ;
2019-08-27 11:04:48 +00:00
self . recover_additional_muts ( ) ;
2019-08-27 17:51:21 +00:00
// Make sure we don't allow e.g. `let mut $p;` where `$p:pat`.
2022-11-22 09:42:01 +00:00
if let token ::Interpolated ( nt ) = & self . token . kind {
2024-04-22 06:29:27 +00:00
if let token ::NtPat ( .. ) = & * * nt {
2023-03-17 09:27:17 +00:00
self . expected_ident_found_err ( ) . emit ( ) ;
2019-08-27 17:51:21 +00:00
}
}
// Parse the pattern we hope to be an identifier.
2023-08-02 16:00:56 +00:00
let mut pat = self . parse_pat_no_top_alt ( Some ( Expected ::Identifier ) , None ) ? ;
2019-08-27 11:04:48 +00:00
2020-02-17 15:03:07 +00:00
// If we don't have `mut $ident (@ pat)?`, error.
2024-04-16 23:23:30 +00:00
if let PatKind ::Ident ( BindingMode ( br @ ByRef ::No , m @ Mutability ::Not ) , .. ) = & mut pat . kind
2022-08-30 22:34:35 +00:00
{
2020-02-17 15:03:07 +00:00
// Don't recurse into the subpattern.
// `mut` on the outer binding doesn't affect the inner bindings.
2024-03-24 01:04:45 +00:00
* br = byref ;
2020-02-17 15:03:07 +00:00
* m = Mutability ::Mut ;
} else {
// Add `mut` to any binding in the parsed pattern.
let changed_any_binding = Self ::make_all_value_bindings_mutable ( & mut pat ) ;
self . ban_mut_general_pat ( mut_span , & pat , changed_any_binding ) ;
2019-08-27 11:04:48 +00:00
}
2024-04-16 23:23:30 +00:00
if matches! ( pat . kind , PatKind ::Ident ( BindingMode ( ByRef ::Yes ( _ ) , Mutability ::Mut ) , .. ) ) {
2024-03-26 05:23:26 +00:00
self . psess . gated_spans . gate ( sym ::mut_ref , pat . span ) ;
}
2020-02-17 15:03:07 +00:00
Ok ( pat . into_inner ( ) . kind )
2019-08-27 11:04:48 +00:00
}
2019-08-27 21:44:44 +00:00
/// 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 P < Pat > ) -> bool {
struct AddMut ( bool ) ;
impl MutVisitor for AddMut {
fn visit_pat ( & mut self , pat : & mut P < Pat > ) {
2024-04-16 23:23:30 +00:00
if let PatKind ::Ident ( BindingMode ( ByRef ::No , m @ Mutability ::Not ) , .. ) =
2022-08-30 22:34:35 +00:00
& mut pat . kind
2020-02-17 15:03:07 +00:00
{
2019-08-27 21:44:44 +00:00
self . 0 = true ;
2020-02-17 15:03:07 +00:00
* m = Mutability ::Mut ;
2019-08-27 21:44:44 +00:00
}
2024-07-10 08:17:13 +00:00
walk_pat ( pat , self ) ;
2019-08-27 21:44:44 +00:00
}
}
let mut add_mut = AddMut ( false ) ;
add_mut . visit_pat ( pat ) ;
add_mut . 0
}
2019-08-27 11:04:48 +00:00
/// Error on `mut $pat` where `$pat` is not an ident.
2019-08-27 21:44:44 +00:00
fn ban_mut_general_pat ( & self , lo : Span , pat : & Pat , changed_any_binding : bool ) {
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( if changed_any_binding {
2023-11-06 19:47:38 +00:00
InvalidMutInPattern ::NestedIdent {
span : lo . to ( pat . span ) ,
2023-11-21 19:07:32 +00:00
pat : pprust ::pat_to_string ( pat ) ,
2023-11-06 19:47:38 +00:00
}
2019-08-12 05:45:55 +00:00
} else {
2023-11-06 19:47:38 +00:00
InvalidMutInPattern ::NonIdent { span : lo . until ( pat . span ) }
2022-10-14 21:16:25 +00:00
} ) ;
2019-08-27 11:04:48 +00:00
}
/// Eat any extraneous `mut`s and error + recover if we ate any.
fn recover_additional_muts ( & mut self ) {
let lo = self . token . span ;
while self . eat_keyword ( kw ::Mut ) { }
if lo = = self . token . span {
return ;
}
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( RepeatedMutInPattern { span : lo . to ( self . prev_token . span ) } ) ;
2019-08-12 05:45:55 +00:00
}
2019-08-12 06:27:01 +00:00
/// Parse macro invocation
2019-12-01 12:55:32 +00:00
fn parse_pat_mac_invoc ( & mut self , path : Path ) -> PResult < ' a , PatKind > {
2019-08-12 06:27:01 +00:00
self . bump ( ) ;
2022-11-18 00:24:21 +00:00
let args = self . parse_delim_args ( ) ? ;
2022-11-16 20:46:06 +00:00
let mac = P ( MacCall { path , args } ) ;
2020-02-29 16:32:20 +00:00
Ok ( PatKind ::MacCall ( mac ) )
2019-08-12 06:27:01 +00:00
}
2019-08-12 09:39:44 +00:00
fn fatal_unexpected_non_pat (
& mut self ,
2024-02-22 23:20:45 +00:00
err : Diag < ' a > ,
2022-11-08 21:03:17 +00:00
expected : Option < Expected > ,
2019-08-12 09:39:44 +00:00
) -> PResult < ' a , P < Pat > > {
2019-09-07 14:38:02 +00:00
err . cancel ( ) ;
2019-08-12 09:39:44 +00:00
2022-11-08 21:03:17 +00:00
let expected = Expected ::to_string_or_fallback ( expected ) ;
2019-12-07 02:07:35 +00:00
let msg = format! ( " expected {} , found {} " , expected , super ::token_descr ( & self . token ) ) ;
2019-08-12 09:39:44 +00:00
2023-12-18 10:09:22 +00:00
let mut err = self . dcx ( ) . struct_span_err ( self . token . span , msg ) ;
2023-07-25 20:00:13 +00:00
err . span_label ( self . token . span , format! ( " expected {expected} " ) ) ;
2019-08-12 09:39:44 +00:00
2024-03-04 05:31:49 +00:00
let sp = self . psess . source_map ( ) . start_point ( self . token . span ) ;
if let Some ( sp ) = self . psess . ambiguous_block_expr_parse . borrow ( ) . get ( & sp ) {
2024-06-18 11:10:18 +00:00
err . subdiagnostic ( ExprParenthesesNeeded ::surrounding ( * sp ) ) ;
2019-08-12 09:39:44 +00:00
}
Err ( err )
}
2019-12-11 09:04:34 +00:00
/// Parses the range pattern end form `".." | "..." | "..=" ;`.
fn parse_range_end ( & mut self ) -> Option < Spanned < RangeEnd > > {
let re = if self . eat ( & token ::DotDotDot ) {
RangeEnd ::Included ( RangeSyntax ::DotDotDot )
} else if self . eat ( & token ::DotDotEq ) {
RangeEnd ::Included ( RangeSyntax ::DotDotEq )
} else if self . eat ( & token ::DotDot ) {
RangeEnd ::Excluded
} else {
return None ;
} ;
2020-02-29 11:56:15 +00:00
Some ( respan ( self . prev_token . span , re ) )
2019-08-11 13:24:37 +00:00
}
2019-12-11 09:04:34 +00:00
/// Parse a range pattern `$begin $form $end?` where `$form = ".." | "..." | "..=" ;`.
/// `$begin $form` has already been parsed.
fn parse_pat_range_begin_with (
& mut self ,
begin : P < Expr > ,
re : Spanned < RangeEnd > ,
) -> PResult < ' a , PatKind > {
let end = if self . is_pat_range_end_start ( 0 ) {
2019-08-11 13:24:37 +00:00
// Parsing e.g. `X..=Y`.
2019-12-11 09:04:34 +00:00
Some ( self . parse_pat_range_end ( ) ? )
2019-08-11 13:24:37 +00:00
} else {
// Parsing e.g. `X..`.
2019-12-11 09:04:34 +00:00
if let RangeEnd ::Included ( _ ) = re . node {
// FIXME(Centril): Consider semantic errors instead in `ast_validation`.
2023-01-28 20:02:00 +00:00
self . inclusive_range_with_incorrect_end ( ) ;
2019-12-11 09:04:34 +00:00
}
None
} ;
Ok ( PatKind ::Range ( Some ( begin ) , end , re ) )
}
2019-08-11 13:24:37 +00:00
2024-02-25 21:22:11 +00:00
pub ( super ) fn inclusive_range_with_incorrect_end ( & mut self ) -> ErrorGuaranteed {
2021-06-26 02:46:41 +00:00
let tok = & self . token ;
2023-01-28 20:02:00 +00:00
let span = self . prev_token . span ;
2021-06-26 02:46:41 +00:00
// If the user typed "..==" instead of "..=", we want to give them
// a specific error message telling them to use "..=".
2023-01-28 20:02:00 +00:00
// If they typed "..=>", suggest they use ".. =>".
2021-06-26 02:46:41 +00:00
// Otherwise, we assume that they meant to type a half open exclusive
// range and give them an error telling them to do that instead.
2023-01-28 20:02:00 +00:00
let no_space = tok . span . lo ( ) = = span . hi ( ) ;
match tok . kind {
token ::Eq if no_space = > {
let span_with_eq = span . to ( tok . span ) ;
2021-06-26 02:46:41 +00:00
2023-01-28 20:02:00 +00:00
// Ensure the user doesn't receive unhelpful unexpected token errors
self . bump ( ) ;
if self . is_pat_range_end_start ( 0 ) {
let _ = self . parse_pat_range_end ( ) . map_err ( | e | e . cancel ( ) ) ;
}
2021-06-26 02:46:41 +00:00
2024-02-25 21:22:11 +00:00
self . dcx ( ) . emit_err ( InclusiveRangeExtraEquals { span : span_with_eq } )
2023-01-28 20:02:00 +00:00
}
token ::Gt if no_space = > {
2024-07-06 03:07:46 +00:00
let after_pat = span . with_hi ( span . hi ( ) - BytePos ( 1 ) ) . shrink_to_hi ( ) ;
2024-02-25 21:22:11 +00:00
self . dcx ( ) . emit_err ( InclusiveRangeMatchArrow { span , arrow : tok . span , after_pat } )
2023-01-28 20:02:00 +00:00
}
2024-07-06 03:07:46 +00:00
_ = > self . dcx ( ) . emit_err ( InclusiveRangeNoEnd {
span ,
suggestion : span . with_lo ( span . hi ( ) - BytePos ( 1 ) ) ,
} ) ,
2021-06-26 02:46:41 +00:00
}
}
2020-01-11 05:49:43 +00:00
/// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
///
/// The form `...X` is prohibited to reduce confusion with the potential
/// expression syntax `...expr` for splatting in expressions.
fn parse_pat_range_to ( & mut self , mut re : Spanned < RangeEnd > ) -> PResult < ' a , PatKind > {
2019-12-11 09:04:34 +00:00
let end = self . parse_pat_range_end ( ) ? ;
2022-11-22 09:42:01 +00:00
if let RangeEnd ::Included ( syn @ RangeSyntax ::DotDotDot ) = & mut re . node {
2020-01-11 05:49:43 +00:00
* syn = RangeSyntax ::DotDotEq ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( DotDotDotRangeToPatternNotAllowed { span : re . span } ) ;
2020-01-11 05:49:43 +00:00
}
2019-12-11 09:04:34 +00:00
Ok ( PatKind ::Range ( None , Some ( end ) , re ) )
}
/// Is the token `dist` away from the current suitable as the start of a range patterns end?
2020-10-19 21:44:37 +00:00
fn is_pat_range_end_start ( & self , dist : usize ) -> bool {
self . check_inline_const ( dist )
2020-10-19 19:18:47 +00:00
| | self . look_ahead ( dist , | t | {
t . is_path_start ( ) // e.g. `MY_CONST`;
2019-12-11 09:04:34 +00:00
| | t . kind = = token ::Dot // e.g. `.5` for recovery;
2024-06-13 03:40:14 +00:00
| | matches! ( t . kind , token ::Literal ( .. ) | token ::BinOp ( token ::Minus ) )
| | t . is_bool_lit ( )
2019-12-11 09:04:34 +00:00
| | t . is_whole_expr ( )
2022-09-01 18:48:09 +00:00
| | t . is_lifetime ( ) // recover `'a` instead of `'a'`
2024-01-03 14:27:58 +00:00
| | ( self . may_recover ( ) // recover leading `(`
& & t . kind = = token ::OpenDelim ( Delimiter ::Parenthesis )
& & self . look_ahead ( dist + 1 , | t | t . kind ! = token ::OpenDelim ( Delimiter ::Parenthesis ) )
& & self . is_pat_range_end_start ( dist + 1 ) )
2020-10-19 19:18:47 +00:00
} )
2019-08-11 13:24:37 +00:00
}
2024-01-03 14:27:58 +00:00
/// Parse a range pattern end bound
2019-08-11 13:24:37 +00:00
fn parse_pat_range_end ( & mut self ) -> PResult < ' a , P < Expr > > {
2024-01-03 14:27:58 +00:00
// recover leading `(`
let open_paren = ( self . may_recover ( )
& & self . eat_noexpect ( & token ::OpenDelim ( Delimiter ::Parenthesis ) ) )
. then_some ( self . prev_token . span ) ;
let bound = if self . check_inline_const ( 0 ) {
2021-11-22 16:25:28 +00:00
self . parse_const_block ( self . token . span , true )
2020-10-19 19:18:47 +00:00
} else if self . check_path ( ) {
2019-08-11 13:24:37 +00:00
let lo = self . token . span ;
let ( qself , path ) = if self . eat_lt ( ) {
// Parse a qualified path
2022-11-16 20:46:06 +00:00
let ( qself , path ) = self . parse_qpath ( PathStyle ::Pat ) ? ;
2019-08-11 13:24:37 +00:00
( Some ( qself ) , path )
} else {
// Parse an unqualified path
2022-11-16 20:46:06 +00:00
( None , self . parse_path ( PathStyle ::Pat ) ? )
2019-08-11 13:24:37 +00:00
} ;
2020-02-29 11:56:15 +00:00
let hi = self . prev_token . span ;
2022-08-14 23:58:38 +00:00
Ok ( self . mk_expr ( lo . to ( hi ) , ExprKind ::Path ( qself , path ) ) )
2019-08-11 13:24:37 +00:00
} else {
self . parse_literal_maybe_minus ( )
2024-01-03 14:27:58 +00:00
} ? ;
2024-01-28 15:12:21 +00:00
let recovered = self . maybe_recover_trailing_expr ( bound . span , true ) ;
2024-01-03 14:27:58 +00:00
// recover trailing `)`
if let Some ( open_paren ) = open_paren {
self . expect ( & token ::CloseDelim ( Delimiter ::Parenthesis ) ) ? ;
self . dcx ( ) . emit_err ( UnexpectedParenInRangePat {
span : vec ! [ open_paren , self . prev_token . span ] ,
sugg : UnexpectedParenInRangePatSugg {
start_span : open_paren ,
end_span : self . prev_token . span ,
} ,
} ) ;
2019-08-11 13:24:37 +00:00
}
2024-01-03 14:27:58 +00:00
2024-01-28 15:12:21 +00:00
Ok ( match recovered {
2024-02-25 21:22:11 +00:00
Some ( guar ) = > self . mk_expr_err ( bound . span , guar ) ,
2024-01-28 15:12:21 +00:00
None = > bound ,
} )
2019-08-11 13:24:37 +00:00
}
2019-08-27 11:04:48 +00:00
/// Is this the start of a pattern beginning with a path?
fn is_start_of_pat_with_path ( & mut self ) -> bool {
self . check_path ( )
// Just for recovery (see `can_be_ident`).
| | self . token . is_ident ( ) & & ! self . token . is_bool_lit ( ) & & ! self . token . is_keyword ( kw ::In )
}
/// Would `parse_pat_ident` be appropriate here?
fn can_be_ident_pat ( & mut self ) -> bool {
self . check_ident ( )
& & ! self . token . is_bool_lit ( ) // Avoid `true` or `false` as a binding as it is a literal.
& & ! self . token . is_path_segment_keyword ( ) // Avoid e.g. `Self` as it is a path.
// Avoid `in`. Due to recovery in the list parser this messes with `for ( $pat in $expr )`.
& & ! self . token . is_keyword ( kw ::In )
2020-10-27 14:55:26 +00:00
// Try to do something more complex?
2022-04-26 12:40:14 +00:00
& & self . look_ahead ( 1 , | t | ! matches! ( t . kind , token ::OpenDelim ( Delimiter ::Parenthesis ) // A tuple struct pattern.
| token ::OpenDelim ( Delimiter ::Brace ) // A struct pattern.
2019-08-27 11:04:48 +00:00
| token ::DotDotDot | token ::DotDotEq | token ::DotDot // A range pattern.
2024-04-04 17:03:32 +00:00
| token ::PathSep // A tuple / struct variant pattern.
2020-10-27 14:55:26 +00:00
| token ::Not ) ) // A macro expanding to a pattern.
2019-08-27 11:04:48 +00:00
}
2019-08-11 13:24:37 +00:00
/// Parses `ident` or `ident @ pat`.
2019-08-12 07:28:30 +00:00
/// Used by the copy foo and ref foo patterns to give a good
2019-08-11 13:24:37 +00:00
/// error message when parsing mistakes like `ref foo(a, b)`.
2023-08-03 08:56:31 +00:00
fn parse_pat_ident (
& mut self ,
2024-04-16 23:23:30 +00:00
binding_annotation : BindingMode ,
2023-08-03 08:56:31 +00:00
syntax_loc : Option < PatternLocation > ,
) -> PResult < ' a , PatKind > {
2023-11-06 21:00:13 +00:00
let ident = self . parse_ident_common ( false ) ? ;
2023-08-03 08:56:31 +00:00
2023-09-12 14:30:38 +00:00
if self . may_recover ( )
& & ! matches! ( syntax_loc , Some ( PatternLocation ::FunctionParameter ) )
2023-08-03 08:56:31 +00:00
& & self . check_noexpect ( & token ::Lt )
& & self . look_ahead ( 1 , | t | t . can_begin_type ( ) )
{
2023-12-18 10:14:02 +00:00
return Err ( self . dcx ( ) . create_err ( GenericArgsInPatRequireTurbofishSyntax {
2023-08-03 08:56:31 +00:00
span : self . token . span ,
suggest_turbofish : self . token . span . shrink_to_lo ( ) ,
} ) ) ;
}
2019-08-11 13:24:37 +00:00
let sub = if self . eat ( & token ::At ) {
2023-08-02 16:00:56 +00:00
Some ( self . parse_pat_no_top_alt ( Some ( Expected ::BindingPattern ) , None ) ? )
2019-08-11 13:24:37 +00:00
} else {
None
} ;
2019-08-12 07:28:30 +00:00
// Just to be friendly, if they write something like `ref Some(i)`,
// we end up here with `(` as the current token.
// This shortly leads to a parse error. Note that if there is no explicit
2019-08-11 13:24:37 +00:00
// binding mode then we do not end up here, because the lookahead
2019-08-12 07:28:30 +00:00
// will direct us over to `parse_enum_variant()`.
2022-04-26 12:40:14 +00:00
if self . token = = token ::OpenDelim ( Delimiter ::Parenthesis ) {
2023-12-18 03:00:17 +00:00
return Err ( self
. dcx ( )
. create_err ( EnumPatternInsteadOfIdentifier { span : self . prev_token . span } ) ) ;
2019-08-11 13:24:37 +00:00
}
2024-01-28 15:12:21 +00:00
// Check for method calls after the `ident`,
// but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.
let pat = if sub . is_none ( )
& & let Some ( guar ) = self . maybe_recover_trailing_expr ( ident . span , false )
{
PatKind ::Err ( guar )
} else {
PatKind ::Ident ( binding_annotation , ident , sub )
} ;
Ok ( pat )
2019-08-11 13:24:37 +00:00
}
2019-08-12 10:27:43 +00:00
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
2022-09-08 00:52:51 +00:00
fn parse_pat_struct ( & mut self , qself : Option < P < QSelf > > , path : Path ) -> PResult < ' a , PatKind > {
2019-08-12 10:27:43 +00:00
if qself . is_some ( ) {
2020-12-10 12:20:07 +00:00
// Feature gate the use of qualified paths in patterns
2024-03-04 05:31:49 +00:00
self . psess . gated_spans . gate ( sym ::more_qualified_paths , path . span ) ;
2019-08-12 10:27:43 +00:00
}
self . bump ( ) ;
let ( fields , etc ) = self . parse_pat_fields ( ) . unwrap_or_else ( | mut e | {
2020-10-02 07:44:16 +00:00
e . span_label ( path . span , " while parsing the fields for this pattern " ) ;
2019-08-12 10:27:43 +00:00
e . emit ( ) ;
self . recover_stmt ( ) ;
2023-12-22 23:29:20 +00:00
// When recovering, pretend we had `Foo { .. }`, to avoid cascading errors.
( ThinVec ::new ( ) , PatFieldsRest ::Rest )
2019-08-12 10:27:43 +00:00
} ) ;
self . bump ( ) ;
2020-12-10 12:20:07 +00:00
Ok ( PatKind ::Struct ( qself , path , fields , etc ) )
2019-08-12 10:27:43 +00:00
}
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
2022-09-08 00:52:51 +00:00
fn parse_pat_tuple_struct (
& mut self ,
qself : Option < P < QSelf > > ,
path : Path ,
) -> PResult < ' a , PatKind > {
2021-07-13 11:18:03 +00:00
let ( fields , _ ) = self . parse_paren_comma_seq ( | p | {
2022-01-12 20:43:24 +00:00
p . parse_pat_allow_top_alt (
None ,
RecoverComma ::No ,
RecoverColon ::No ,
CommaRecoveryMode ::EitherTupleOrPipe ,
)
2021-07-13 11:18:03 +00:00
} ) ? ;
2020-12-10 12:20:07 +00:00
if qself . is_some ( ) {
2024-03-04 05:31:49 +00:00
self . psess . gated_spans . gate ( sym ::more_qualified_paths , path . span ) ;
2020-12-10 12:20:07 +00:00
}
Ok ( PatKind ::TupleStruct ( qself , path , fields ) )
2019-12-31 02:36:45 +00:00
}
2022-06-08 04:40:55 +00:00
/// Are we sure this could not possibly be the start of a pattern?
///
/// Currently, this only accounts for tokens that can follow identifiers
/// in patterns, but this can be extended as necessary.
fn isnt_pattern_start ( & self ) -> bool {
[
token ::Eq ,
token ::Colon ,
token ::Comma ,
token ::Semi ,
token ::At ,
token ::OpenDelim ( Delimiter ::Brace ) ,
token ::CloseDelim ( Delimiter ::Brace ) ,
token ::CloseDelim ( Delimiter ::Parenthesis ) ,
]
. contains ( & self . token . kind )
}
2024-03-20 20:53:50 +00:00
fn parse_pat_builtin ( & mut self ) -> PResult < ' a , PatKind > {
self . parse_builtin ( | self_ , _lo , ident | {
Ok ( match ident . name {
// builtin#deref(PAT)
sym ::deref = > Some ( ast ::PatKind ::Deref ( self_ . parse_pat_allow_top_alt (
None ,
RecoverComma ::Yes ,
RecoverColon ::Yes ,
CommaRecoveryMode ::LikelyTuple ,
) ? ) ) ,
_ = > None ,
} )
} )
}
2022-06-08 04:40:55 +00:00
/// Parses `box pat`
fn parse_pat_box ( & mut self ) -> PResult < ' a , PatKind > {
let box_span = self . prev_token . span ;
if self . isnt_pattern_start ( ) {
2023-04-27 00:53:06 +00:00
let descr = super ::token_descr ( & self . token ) ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( errors ::BoxNotPat {
2023-04-27 00:53:06 +00:00
span : self . token . span ,
kw : box_span ,
lo : box_span . shrink_to_lo ( ) ,
descr ,
} ) ;
2022-06-08 04:40:55 +00:00
// We cannot use `parse_pat_ident()` since it will complain `box`
// is not an identifier.
let sub = if self . eat ( & token ::At ) {
2023-08-02 16:00:56 +00:00
Some ( self . parse_pat_no_top_alt ( Some ( Expected ::BindingPattern ) , None ) ? )
2022-06-08 04:40:55 +00:00
} else {
None
} ;
2024-04-16 23:23:30 +00:00
Ok ( PatKind ::Ident ( BindingMode ::NONE , Ident ::new ( kw ::Box , box_span ) , sub ) )
2022-06-08 04:40:55 +00:00
} else {
2023-08-02 16:00:56 +00:00
let pat = self . parse_pat_with_range_pat ( false , None , None ) ? ;
2024-03-04 05:31:49 +00:00
self . psess . gated_spans . gate ( sym ::box_patterns , box_span . to ( self . prev_token . span ) ) ;
2022-06-08 04:40:55 +00:00
Ok ( PatKind ::Box ( pat ) )
}
}
2019-08-11 13:24:37 +00:00
/// Parses the fields of a struct-like pattern.
2023-12-22 23:29:20 +00:00
fn parse_pat_fields ( & mut self ) -> PResult < ' a , ( ThinVec < PatField > , PatFieldsRest ) > {
2023-01-30 03:58:23 +00:00
let mut fields = ThinVec ::new ( ) ;
2023-12-22 23:29:20 +00:00
let mut etc = PatFieldsRest ::None ;
2019-08-11 13:24:37 +00:00
let mut ate_comma = true ;
2024-02-22 23:20:45 +00:00
let mut delayed_err : Option < Diag < ' a > > = None ;
2023-06-02 06:40:44 +00:00
let mut first_etc_and_maybe_comma_span = None ;
let mut last_non_comma_dotdot_span = None ;
2019-08-11 13:24:37 +00:00
2022-04-26 12:40:14 +00:00
while self . token ! = token ::CloseDelim ( Delimiter ::Brace ) {
2019-08-11 13:24:37 +00:00
let attrs = match self . parse_outer_attributes ( ) {
Ok ( attrs ) = > attrs ,
Err ( err ) = > {
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
if let Some ( delayed ) = delayed_err {
2019-08-11 13:24:37 +00:00
delayed . emit ( ) ;
}
return Err ( err ) ;
}
} ;
let lo = self . token . span ;
// check that a comma comes after every field
if ! ate_comma {
2023-12-18 03:00:17 +00:00
let mut err =
self . dcx ( ) . create_err ( ExpectedCommaAfterPatternField { span : self . token . span } ) ;
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
if let Some ( delayed ) = delayed_err {
2019-08-11 13:24:37 +00:00
delayed . emit ( ) ;
}
2023-10-27 16:11:43 +00:00
self . recover_misplaced_pattern_modifiers ( & fields , & mut err ) ;
2019-08-11 13:24:37 +00:00
return Err ( err ) ;
}
ate_comma = false ;
2023-01-15 21:31:04 +00:00
if self . check ( & token ::DotDot )
| | self . check_noexpect ( & token ::DotDotDot )
| | self . check_keyword ( kw ::Underscore )
{
2023-12-22 23:29:20 +00:00
etc = PatFieldsRest ::Rest ;
2019-08-11 13:24:37 +00:00
let mut etc_sp = self . token . span ;
2023-06-02 06:40:44 +00:00
if first_etc_and_maybe_comma_span . is_none ( ) {
if let Some ( comma_tok ) = self
. look_ahead ( 1 , | t | if * t = = token ::Comma { Some ( t . clone ( ) ) } else { None } )
{
let nw_span = self
2024-03-04 05:31:49 +00:00
. psess
2023-06-02 06:40:44 +00:00
. source_map ( )
. span_extend_to_line ( comma_tok . span )
. trim_start ( comma_tok . span . shrink_to_lo ( ) )
2024-03-04 05:31:49 +00:00
. map ( | s | self . psess . source_map ( ) . span_until_non_whitespace ( s ) ) ;
2023-06-02 06:40:44 +00:00
first_etc_and_maybe_comma_span = nw_span . map ( | s | etc_sp . to ( s ) ) ;
} else {
first_etc_and_maybe_comma_span =
2024-03-04 05:31:49 +00:00
Some ( self . psess . source_map ( ) . span_until_non_whitespace ( etc_sp ) ) ;
2023-06-02 06:40:44 +00:00
}
}
2019-08-11 13:24:37 +00:00
2023-01-15 21:31:04 +00:00
self . recover_bad_dot_dot ( ) ;
self . bump ( ) ; // `..` || `...` || `_`
2019-08-11 13:24:37 +00:00
2022-04-26 12:40:14 +00:00
if self . token = = token ::CloseDelim ( Delimiter ::Brace ) {
2019-08-11 13:24:37 +00:00
break ;
}
2019-12-07 02:07:35 +00:00
let token_str = super ::token_descr ( & self . token ) ;
2023-07-25 20:00:13 +00:00
let msg = format! ( " expected ` }} `, found {token_str} " ) ;
2023-12-18 10:09:22 +00:00
let mut err = self . dcx ( ) . struct_span_err ( self . token . span , msg ) ;
2019-08-11 13:24:37 +00:00
err . span_label ( self . token . span , " expected `}` " ) ;
let mut comma_sp = None ;
if self . token = = token ::Comma {
// Issue #49257
2024-03-04 05:31:49 +00:00
let nw_span =
self . psess . source_map ( ) . span_until_non_whitespace ( self . token . span ) ;
2019-08-11 13:24:37 +00:00
etc_sp = etc_sp . to ( nw_span ) ;
err . span_label (
etc_sp ,
" `..` must be at the end and cannot have a trailing comma " ,
) ;
comma_sp = Some ( self . token . span ) ;
self . bump ( ) ;
ate_comma = true ;
}
2022-04-26 12:40:14 +00:00
if self . token = = token ::CloseDelim ( Delimiter ::Brace ) {
2019-08-11 13:24:37 +00:00
// If the struct looks otherwise well formed, recover and continue.
if let Some ( sp ) = comma_sp {
err . span_suggestion_short (
sp ,
" remove this comma " ,
2022-06-13 06:48:40 +00:00
" " ,
2019-08-11 13:24:37 +00:00
Applicability ::MachineApplicable ,
) ;
}
err . emit ( ) ;
break ;
} else if self . token . is_ident ( ) & & ate_comma {
// Accept fields coming after `..,`.
// This way we avoid "pattern missing fields" errors afterwards.
// We delay this error until the end in order to have a span for a
// suggested fix.
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
if let Some ( delayed_err ) = delayed_err {
2019-08-11 13:24:37 +00:00
delayed_err . emit ( ) ;
return Err ( err ) ;
} else {
delayed_err = Some ( err ) ;
}
} else {
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
if let Some ( err ) = delayed_err {
2019-08-11 13:24:37 +00:00
err . emit ( ) ;
}
return Err ( err ) ;
}
}
2021-01-22 18:28:08 +00:00
let field =
self . collect_tokens_trailing_token ( attrs , ForceCollect ::No , | this , attrs | {
let field = match this . parse_pat_field ( lo , attrs ) {
Ok ( field ) = > Ok ( field ) ,
Err ( err ) = > {
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 01:17:35 +00:00
if let Some ( delayed_err ) = delayed_err . take ( ) {
2021-01-22 18:28:08 +00:00
delayed_err . emit ( ) ;
}
return Err ( err ) ;
}
} ? ;
ate_comma = this . eat ( & token ::Comma ) ;
2023-06-02 06:40:44 +00:00
last_non_comma_dotdot_span = Some ( this . prev_token . span ) ;
2024-07-16 14:12:24 +00:00
// We just ate a comma, so there's no need to capture a trailing token.
Ok ( ( field , false ) )
2021-01-22 18:28:08 +00:00
} ) ? ;
fields . push ( field )
2019-08-11 13:24:37 +00:00
}
if let Some ( mut err ) = delayed_err {
2023-06-02 06:40:44 +00:00
if let Some ( first_etc_span ) = first_etc_and_maybe_comma_span {
if self . prev_token = = token ::DotDot {
// We have `.., x, ..`.
err . multipart_suggestion (
" remove the starting `..` " ,
vec! [ ( first_etc_span , String ::new ( ) ) ] ,
Applicability ::MachineApplicable ,
) ;
} else {
if let Some ( last_non_comma_dotdot_span ) = last_non_comma_dotdot_span {
// We have `.., x`.
err . multipart_suggestion (
" move the `..` to the end of the field list " ,
vec! [
( first_etc_span , String ::new ( ) ) ,
(
self . token . span . to ( last_non_comma_dotdot_span . shrink_to_hi ( ) ) ,
format! ( " {} .. }} " , if ate_comma { " " } else { " , " } ) ,
) ,
] ,
Applicability ::MachineApplicable ,
) ;
}
}
2019-08-11 13:24:37 +00:00
}
err . emit ( ) ;
}
2020-03-20 14:03:11 +00:00
Ok ( ( fields , etc ) )
2019-08-11 13:24:37 +00:00
}
2023-10-27 16:11:43 +00:00
/// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest
/// the correct code.
2024-02-22 23:20:45 +00:00
fn recover_misplaced_pattern_modifiers ( & self , fields : & ThinVec < PatField > , err : & mut Diag < ' a > ) {
2023-10-27 16:11:43 +00:00
if let Some ( last ) = fields . iter ( ) . last ( )
& & last . is_shorthand
& & let PatKind ::Ident ( binding , ident , None ) = last . pat . kind
2024-04-16 23:23:30 +00:00
& & binding ! = BindingMode ::NONE
2023-10-27 16:11:43 +00:00
& & self . token = = token ::Colon
// We found `ref mut? ident:`, try to parse a `name,` or `name }`.
& & let Some ( name_span ) = self . look_ahead ( 1 , | t | t . is_ident ( ) . then ( | | t . span ) )
& & self . look_ahead ( 2 , | t | {
t = = & token ::Comma | | t = = & token ::CloseDelim ( Delimiter ::Brace )
} )
{
let span = last . pat . span . with_hi ( ident . span . lo ( ) ) ;
// We have `S { ref field: name }` instead of `S { field: ref name }`
err . multipart_suggestion (
" the pattern modifiers belong after the `:` " ,
vec! [
( span , String ::new ( ) ) ,
( name_span . shrink_to_lo ( ) , binding . prefix_str ( ) . to_string ( ) ) ,
] ,
Applicability ::MachineApplicable ,
) ;
}
}
2023-01-15 21:31:04 +00:00
/// Recover on `...` or `_` as if it were `..` to avoid further errors.
2019-08-12 10:27:43 +00:00
/// See issue #46718.
2023-01-15 21:31:04 +00:00
fn recover_bad_dot_dot ( & self ) {
if self . token = = token ::DotDot {
2019-08-12 10:27:43 +00:00
return ;
}
2023-01-15 21:31:04 +00:00
let token_str = pprust ::token_to_string ( & self . token ) ;
2023-12-18 10:14:02 +00:00
self . dcx ( ) . emit_err ( DotDotDotForRemainingFields { span : self . token . span , token_str } ) ;
2019-08-12 10:27:43 +00:00
}
2022-08-17 02:34:33 +00:00
fn parse_pat_field ( & mut self , lo : Span , attrs : AttrVec ) -> PResult < ' a , PatField > {
2019-08-11 13:24:37 +00:00
// Check if a colon exists one ahead. This means we're parsing a fieldname.
let hi ;
let ( subpat , fieldname , is_shorthand ) = if self . look_ahead ( 1 , | t | t = = & token ::Colon ) {
2019-09-06 02:56:45 +00:00
// Parsing a pattern of the form `fieldname: pat`.
2019-08-11 13:24:37 +00:00
let fieldname = self . parse_field_name ( ) ? ;
self . bump ( ) ;
2022-01-12 20:43:24 +00:00
let pat = self . parse_pat_allow_top_alt (
None ,
RecoverComma ::No ,
RecoverColon ::No ,
CommaRecoveryMode ::EitherTupleOrPipe ,
) ? ;
2019-08-11 13:24:37 +00:00
hi = pat . span ;
( pat , fieldname , false )
} else {
2019-09-06 02:56:45 +00:00
// Parsing a pattern of the form `(box) (ref) (mut) fieldname`.
2019-08-11 13:24:37 +00:00
let is_box = self . eat_keyword ( kw ::Box ) ;
let boxed_span = self . token . span ;
2024-03-24 01:04:45 +00:00
let mutability = self . parse_mutability ( ) ;
let by_ref = self . parse_byref ( ) ;
2021-01-21 02:49:11 +00:00
let fieldname = self . parse_field_name ( ) ? ;
2020-02-29 11:56:15 +00:00
hi = self . prev_token . span ;
2024-04-16 23:23:30 +00:00
let ann = BindingMode ( by_ref , mutability ) ;
2022-08-30 22:34:35 +00:00
let fieldpat = self . mk_pat_ident ( boxed_span . to ( hi ) , ann , fieldname ) ;
2019-08-11 13:24:37 +00:00
let subpat =
if is_box { self . mk_pat ( lo . to ( hi ) , PatKind ::Box ( fieldpat ) ) } else { fieldpat } ;
( subpat , fieldname , true )
} ;
2021-03-15 21:36:07 +00:00
Ok ( PatField {
2019-08-14 23:35:36 +00:00
ident : fieldname ,
pat : subpat ,
is_shorthand ,
2022-08-17 02:34:33 +00:00
attrs ,
2019-08-14 23:35:36 +00:00
id : ast ::DUMMY_NODE_ID ,
2019-08-11 13:24:37 +00:00
span : lo . to ( hi ) ,
2019-09-09 12:26:25 +00:00
is_placeholder : false ,
2019-08-11 13:24:37 +00:00
} )
}
2024-04-16 23:23:30 +00:00
pub ( super ) fn mk_pat_ident ( & self , span : Span , ann : BindingMode , ident : Ident ) -> P < Pat > {
2022-08-30 22:34:35 +00:00
self . mk_pat ( span , PatKind ::Ident ( ann , ident , None ) )
2019-08-11 13:24:37 +00:00
}
2021-11-21 04:56:32 +00:00
pub ( super ) fn mk_pat ( & self , span : Span , kind : PatKind ) -> P < Pat > {
2020-07-27 22:02:29 +00:00
P ( Pat { kind , span , id : ast ::DUMMY_NODE_ID , tokens : None } )
2019-08-11 13:24:37 +00:00
}
}