]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_parse/src/parser/expr.rs
review comment: add test case
[rust.git] / compiler / rustc_parse / src / parser / expr.rs
1 use super::diagnostics::SnapshotParser;
2 use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
3 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
4 use super::{
5     AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
6     SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
7 };
8 use crate::errors::{
9     ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
10     BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric,
11     ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
12     ExpectedElseBlock, ExpectedEqForLetExpr, ExpectedExpressionFoundLet,
13     FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
14     IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub,
15     InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
16     InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator,
17     InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
18     LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
19     MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
20     MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
21     NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
22     OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
23     RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
24     StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf,
25     UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
26 };
27 use crate::maybe_recover_from_interpolated_ty_qpath;
28 use core::mem;
29 use rustc_ast::ptr::P;
30 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
31 use rustc_ast::tokenstream::Spacing;
32 use rustc_ast::util::case::Case;
33 use rustc_ast::util::classify;
34 use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
35 use rustc_ast::visit::Visitor;
36 use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID};
37 use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
38 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
39 use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
40 use rustc_ast_pretty::pprust;
41 use rustc_errors::{
42     Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
43     StashKey,
44 };
45 use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
46 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
47 use rustc_session::lint::BuiltinLintDiagnostics;
48 use rustc_span::source_map::{self, Span, Spanned};
49 use rustc_span::symbol::{kw, sym, Ident, Symbol};
50 use rustc_span::{BytePos, Pos};
51
52 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
53 /// dropped into the token stream, which happens while parsing the result of
54 /// macro expansion). Placement of these is not as complex as I feared it would
55 /// be. The important thing is to make sure that lookahead doesn't balk at
56 /// `token::Interpolated` tokens.
57 macro_rules! maybe_whole_expr {
58     ($p:expr) => {
59         if let token::Interpolated(nt) = &$p.token.kind {
60             match &**nt {
61                 token::NtExpr(e) | token::NtLiteral(e) => {
62                     let e = e.clone();
63                     $p.bump();
64                     return Ok(e);
65                 }
66                 token::NtPath(path) => {
67                     let path = (**path).clone();
68                     $p.bump();
69                     return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path)));
70                 }
71                 token::NtBlock(block) => {
72                     let block = block.clone();
73                     $p.bump();
74                     return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None)));
75                 }
76                 _ => {}
77             };
78         }
79     };
80 }
81
82 #[derive(Debug)]
83 pub(super) enum LhsExpr {
84     NotYetParsed,
85     AttributesParsed(AttrWrapper),
86     AlreadyParsed(P<Expr>),
87 }
88
89 impl From<Option<AttrWrapper>> for LhsExpr {
90     /// Converts `Some(attrs)` into `LhsExpr::AttributesParsed(attrs)`
91     /// and `None` into `LhsExpr::NotYetParsed`.
92     ///
93     /// This conversion does not allocate.
94     fn from(o: Option<AttrWrapper>) -> Self {
95         if let Some(attrs) = o { LhsExpr::AttributesParsed(attrs) } else { LhsExpr::NotYetParsed }
96     }
97 }
98
99 impl From<P<Expr>> for LhsExpr {
100     /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed(expr)`.
101     ///
102     /// This conversion does not allocate.
103     fn from(expr: P<Expr>) -> Self {
104         LhsExpr::AlreadyParsed(expr)
105     }
106 }
107
108 impl<'a> Parser<'a> {
109     /// Parses an expression.
110     #[inline]
111     pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
112         self.current_closure.take();
113
114         self.parse_expr_res(Restrictions::empty(), None)
115     }
116
117     /// Parses an expression, forcing tokens to be collected
118     pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
119         self.collect_tokens_no_attrs(|this| this.parse_expr())
120     }
121
122     pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
123         self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
124     }
125
126     fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P<Expr>> {
127         match self.parse_expr() {
128             Ok(expr) => Ok(expr),
129             Err(mut err) => match self.token.ident() {
130                 Some((Ident { name: kw::Underscore, .. }, false))
131                     if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
132                 {
133                     // Special-case handling of `foo(_, _, _)`
134                     err.emit();
135                     self.bump();
136                     Ok(self.mk_expr(self.prev_token.span, ExprKind::Err))
137                 }
138                 _ => Err(err),
139             },
140         }
141     }
142
143     /// Parses a sequence of expressions delimited by parentheses.
144     fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
145         self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
146     }
147
148     /// Parses an expression, subject to the given restrictions.
149     #[inline]
150     pub(super) fn parse_expr_res(
151         &mut self,
152         r: Restrictions,
153         already_parsed_attrs: Option<AttrWrapper>,
154     ) -> PResult<'a, P<Expr>> {
155         self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
156     }
157
158     /// Parses an associative expression.
159     ///
160     /// This parses an expression accounting for associativity and precedence of the operators in
161     /// the expression.
162     #[inline]
163     fn parse_assoc_expr(
164         &mut self,
165         already_parsed_attrs: Option<AttrWrapper>,
166     ) -> PResult<'a, P<Expr>> {
167         self.parse_assoc_expr_with(0, already_parsed_attrs.into())
168     }
169
170     /// Parses an associative expression with operators of at least `min_prec` precedence.
171     pub(super) fn parse_assoc_expr_with(
172         &mut self,
173         min_prec: usize,
174         lhs: LhsExpr,
175     ) -> PResult<'a, P<Expr>> {
176         let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs {
177             expr
178         } else {
179             let attrs = match lhs {
180                 LhsExpr::AttributesParsed(attrs) => Some(attrs),
181                 _ => None,
182             };
183             if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind) {
184                 return self.parse_prefix_range_expr(attrs);
185             } else {
186                 self.parse_prefix_expr(attrs)?
187             }
188         };
189         let last_type_ascription_set = self.last_type_ascription.is_some();
190
191         if !self.should_continue_as_assoc_expr(&lhs) {
192             self.last_type_ascription = None;
193             return Ok(lhs);
194         }
195
196         self.expected_tokens.push(TokenType::Operator);
197         while let Some(op) = self.check_assoc_op() {
198             // Adjust the span for interpolated LHS to point to the `$lhs` token
199             // and not to what it refers to.
200             let lhs_span = match self.prev_token.kind {
201                 TokenKind::Interpolated(..) => self.prev_token.span,
202                 _ => lhs.span,
203             };
204
205             let cur_op_span = self.token.span;
206             let restrictions = if op.node.is_assign_like() {
207                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
208             } else {
209                 self.restrictions
210             };
211             let prec = op.node.precedence();
212             if prec < min_prec {
213                 break;
214             }
215             // Check for deprecated `...` syntax
216             if self.token == token::DotDotDot && op.node == AssocOp::DotDotEq {
217                 self.err_dotdotdot_syntax(self.token.span);
218             }
219
220             if self.token == token::LArrow {
221                 self.err_larrow_operator(self.token.span);
222             }
223
224             self.bump();
225             if op.node.is_comparison() {
226                 if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
227                     return Ok(expr);
228                 }
229             }
230
231             // Look for JS' `===` and `!==` and recover
232             if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual)
233                 && self.token.kind == token::Eq
234                 && self.prev_token.span.hi() == self.token.span.lo()
235             {
236                 let sp = op.span.to(self.token.span);
237                 let sugg = match op.node {
238                     AssocOp::Equal => "==",
239                     AssocOp::NotEqual => "!=",
240                     _ => unreachable!(),
241                 }
242                 .into();
243                 let invalid = format!("{}=", &sugg);
244                 self.sess.emit_err(InvalidComparisonOperator {
245                     span: sp,
246                     invalid: invalid.clone(),
247                     sub: InvalidComparisonOperatorSub::Correctable {
248                         span: sp,
249                         invalid,
250                         correct: sugg,
251                     },
252                 });
253                 self.bump();
254             }
255
256             // Look for PHP's `<>` and recover
257             if op.node == AssocOp::Less
258                 && self.token.kind == token::Gt
259                 && self.prev_token.span.hi() == self.token.span.lo()
260             {
261                 let sp = op.span.to(self.token.span);
262                 self.sess.emit_err(InvalidComparisonOperator {
263                     span: sp,
264                     invalid: "<>".into(),
265                     sub: InvalidComparisonOperatorSub::Correctable {
266                         span: sp,
267                         invalid: "<>".into(),
268                         correct: "!=".into(),
269                     },
270                 });
271                 self.bump();
272             }
273
274             // Look for C++'s `<=>` and recover
275             if op.node == AssocOp::LessEqual
276                 && self.token.kind == token::Gt
277                 && self.prev_token.span.hi() == self.token.span.lo()
278             {
279                 let sp = op.span.to(self.token.span);
280                 self.sess.emit_err(InvalidComparisonOperator {
281                     span: sp,
282                     invalid: "<=>".into(),
283                     sub: InvalidComparisonOperatorSub::Spaceship(sp),
284                 });
285                 self.bump();
286             }
287
288             if self.prev_token == token::BinOp(token::Plus)
289                 && self.token == token::BinOp(token::Plus)
290                 && self.prev_token.span.between(self.token.span).is_empty()
291             {
292                 let op_span = self.prev_token.span.to(self.token.span);
293                 // Eat the second `+`
294                 self.bump();
295                 lhs = self.recover_from_postfix_increment(lhs, op_span)?;
296                 continue;
297             }
298
299             let op = op.node;
300             // Special cases:
301             if op == AssocOp::As {
302                 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
303                 continue;
304             } else if op == AssocOp::Colon {
305                 lhs = self.parse_assoc_op_ascribe(lhs, lhs_span)?;
306                 continue;
307             } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
308                 // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
309                 // generalise it to the Fixity::None code.
310                 lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
311                 break;
312             }
313
314             let fixity = op.fixity();
315             let prec_adjustment = match fixity {
316                 Fixity::Right => 0,
317                 Fixity::Left => 1,
318                 // We currently have no non-associative operators that are not handled above by
319                 // the special cases. The code is here only for future convenience.
320                 Fixity::None => 1,
321             };
322             let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
323                 this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
324             })?;
325
326             let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
327             lhs = match op {
328                 AssocOp::Add
329                 | AssocOp::Subtract
330                 | AssocOp::Multiply
331                 | AssocOp::Divide
332                 | AssocOp::Modulus
333                 | AssocOp::LAnd
334                 | AssocOp::LOr
335                 | AssocOp::BitXor
336                 | AssocOp::BitAnd
337                 | AssocOp::BitOr
338                 | AssocOp::ShiftLeft
339                 | AssocOp::ShiftRight
340                 | AssocOp::Equal
341                 | AssocOp::Less
342                 | AssocOp::LessEqual
343                 | AssocOp::NotEqual
344                 | AssocOp::Greater
345                 | AssocOp::GreaterEqual => {
346                     let ast_op = op.to_ast_binop().unwrap();
347                     let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
348                     self.mk_expr(span, binary)
349                 }
350                 AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
351                 AssocOp::AssignOp(k) => {
352                     let aop = match k {
353                         token::Plus => BinOpKind::Add,
354                         token::Minus => BinOpKind::Sub,
355                         token::Star => BinOpKind::Mul,
356                         token::Slash => BinOpKind::Div,
357                         token::Percent => BinOpKind::Rem,
358                         token::Caret => BinOpKind::BitXor,
359                         token::And => BinOpKind::BitAnd,
360                         token::Or => BinOpKind::BitOr,
361                         token::Shl => BinOpKind::Shl,
362                         token::Shr => BinOpKind::Shr,
363                     };
364                     let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
365                     self.mk_expr(span, aopexpr)
366                 }
367                 AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
368                     self.span_bug(span, "AssocOp should have been handled by special case")
369                 }
370             };
371
372             if let Fixity::None = fixity {
373                 break;
374             }
375         }
376         if last_type_ascription_set {
377             self.last_type_ascription = None;
378         }
379         Ok(lhs)
380     }
381
382     fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
383         match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
384             // Semi-statement forms are odd:
385             // See https://github.com/rust-lang/rust/issues/29071
386             (true, None) => false,
387             (false, _) => true, // Continue parsing the expression.
388             // An exhaustive check is done in the following block, but these are checked first
389             // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
390             // want to keep their span info to improve diagnostics in these cases in a later stage.
391             (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
392             (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
393             (true, Some(AssocOp::Add)) // `{ 42 } + 42
394             // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
395             // `if x { a } else { b } && if y { c } else { d }`
396             if !self.look_ahead(1, |t| t.is_used_keyword()) => {
397                 // These cases are ambiguous and can't be identified in the parser alone.
398                 let sp = self.sess.source_map().start_point(self.token.span);
399                 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
400                 false
401             }
402             (true, Some(AssocOp::LAnd)) |
403             (true, Some(AssocOp::LOr)) |
404             (true, Some(AssocOp::BitOr)) => {
405                 // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
406                 // above due to #74233.
407                 // These cases are ambiguous and can't be identified in the parser alone.
408                 //
409                 // Bitwise AND is left out because guessing intent is hard. We can make
410                 // suggestions based on the assumption that double-refs are rarely intentional,
411                 // and closures are distinct enough that they don't get mixed up with their
412                 // return value.
413                 let sp = self.sess.source_map().start_point(self.token.span);
414                 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
415                 false
416             }
417             (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
418             (true, Some(_)) => {
419                 self.error_found_expr_would_be_stmt(lhs);
420                 true
421             }
422         }
423     }
424
425     /// We've found an expression that would be parsed as a statement,
426     /// but the next token implies this should be parsed as an expression.
427     /// For example: `if let Some(x) = x { x } else { 0 } / 2`.
428     fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
429         self.sess.emit_err(FoundExprWouldBeStmt {
430             span: self.token.span,
431             token: self.token.clone(),
432             suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
433         });
434     }
435
436     /// Possibly translate the current token to an associative operator.
437     /// The method does not advance the current token.
438     ///
439     /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
440     fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
441         let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
442             // When parsing const expressions, stop parsing when encountering `>`.
443             (
444                 Some(
445                     AssocOp::ShiftRight
446                     | AssocOp::Greater
447                     | AssocOp::GreaterEqual
448                     | AssocOp::AssignOp(token::BinOpToken::Shr),
449                 ),
450                 _,
451             ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
452                 return None;
453             }
454             (Some(op), _) => (op, self.token.span),
455             (None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
456                 self.sess.emit_err(InvalidLogicalOperator {
457                     span: self.token.span,
458                     incorrect: "and".into(),
459                     sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
460                 });
461                 (AssocOp::LAnd, span)
462             }
463             (None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => {
464                 self.sess.emit_err(InvalidLogicalOperator {
465                     span: self.token.span,
466                     incorrect: "or".into(),
467                     sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
468                 });
469                 (AssocOp::LOr, span)
470             }
471             _ => return None,
472         };
473         Some(source_map::respan(span, op))
474     }
475
476     /// Checks if this expression is a successfully parsed statement.
477     fn expr_is_complete(&self, e: &Expr) -> bool {
478         self.restrictions.contains(Restrictions::STMT_EXPR)
479             && !classify::expr_requires_semi_to_be_stmt(e)
480     }
481
482     /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
483     /// The other two variants are handled in `parse_prefix_range_expr` below.
484     fn parse_range_expr(
485         &mut self,
486         prec: usize,
487         lhs: P<Expr>,
488         op: AssocOp,
489         cur_op_span: Span,
490     ) -> PResult<'a, P<Expr>> {
491         let rhs = if self.is_at_start_of_range_notation_rhs() {
492             Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
493         } else {
494             None
495         };
496         let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
497         let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
498         let limits =
499             if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
500         let range = self.mk_range(Some(lhs), rhs, limits);
501         Ok(self.mk_expr(span, range))
502     }
503
504     fn is_at_start_of_range_notation_rhs(&self) -> bool {
505         if self.token.can_begin_expr() {
506             // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
507             if self.token == token::OpenDelim(Delimiter::Brace) {
508                 return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
509             }
510             true
511         } else {
512             false
513         }
514     }
515
516     /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
517     fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
518         // Check for deprecated `...` syntax.
519         if self.token == token::DotDotDot {
520             self.err_dotdotdot_syntax(self.token.span);
521         }
522
523         debug_assert!(
524             [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind),
525             "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
526             self.token
527         );
528
529         let limits = match self.token.kind {
530             token::DotDot => RangeLimits::HalfOpen,
531             _ => RangeLimits::Closed,
532         };
533         let op = AssocOp::from_token(&self.token);
534         // FIXME: `parse_prefix_range_expr` is called when the current
535         // token is `DotDot`, `DotDotDot`, or `DotDotEq`. If we haven't already
536         // parsed attributes, then trying to parse them here will always fail.
537         // We should figure out how we want attributes on range expressions to work.
538         let attrs = self.parse_or_use_outer_attributes(attrs)?;
539         self.collect_tokens_for_expr(attrs, |this, attrs| {
540             let lo = this.token.span;
541             this.bump();
542             let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
543                 // RHS must be parsed with more associativity than the dots.
544                 this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
545                     .map(|x| (lo.to(x.span), Some(x)))?
546             } else {
547                 (lo, None)
548             };
549             let range = this.mk_range(None, opt_end, limits);
550             Ok(this.mk_expr_with_attrs(span, range, attrs))
551         })
552     }
553
554     /// Parses a prefix-unary-operator expr.
555     fn parse_prefix_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
556         let attrs = self.parse_or_use_outer_attributes(attrs)?;
557         let lo = self.token.span;
558
559         macro_rules! make_it {
560             ($this:ident, $attrs:expr, |this, _| $body:expr) => {
561                 $this.collect_tokens_for_expr($attrs, |$this, attrs| {
562                     let (hi, ex) = $body?;
563                     Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs))
564                 })
565             };
566         }
567
568         let this = self;
569
570         // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
571         match this.token.uninterpolate().kind {
572             token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr`
573             token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr`
574             token::BinOp(token::Minus) => {
575                 make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
576             } // `-expr`
577             token::BinOp(token::Star) => {
578                 make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
579             } // `*expr`
580             token::BinOp(token::And) | token::AndAnd => {
581                 make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
582             }
583             token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
584                 let mut err =
585                     LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
586
587                 // a block on the LHS might have been intended to be an expression instead
588                 if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
589                     err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
590                 } else {
591                     err.remove_plus = Some(lo);
592                 }
593                 this.sess.emit_err(err);
594
595                 this.bump();
596                 this.parse_prefix_expr(None)
597             } // `+expr`
598             // Recover from `++x`:
599             token::BinOp(token::Plus)
600                 if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
601             {
602                 let prev_is_semi = this.prev_token == token::Semi;
603                 let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
604                 // Eat both `+`s.
605                 this.bump();
606                 this.bump();
607
608                 let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
609                 this.recover_from_prefix_increment(operand_expr, pre_span, prev_is_semi)
610             }
611             token::Ident(..) if this.token.is_keyword(kw::Box) => {
612                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
613             }
614             token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
615                 make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
616             }
617             _ => return this.parse_dot_or_call_expr(Some(attrs)),
618         }
619     }
620
621     fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
622         self.bump();
623         let expr = self.parse_prefix_expr(None);
624         let (span, expr) = self.interpolated_or_expr_span(expr)?;
625         Ok((lo.to(span), expr))
626     }
627
628     fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
629         let (span, expr) = self.parse_prefix_expr_common(lo)?;
630         Ok((span, self.mk_unary(op, expr)))
631     }
632
633     // Recover on `!` suggesting for bitwise negation instead.
634     fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
635         self.sess.emit_err(TildeAsUnaryOperator(lo));
636
637         self.parse_unary_expr(lo, UnOp::Not)
638     }
639
640     /// Parse `box expr`.
641     fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
642         let (span, expr) = self.parse_prefix_expr_common(lo)?;
643         self.sess.gated_spans.gate(sym::box_syntax, span);
644         Ok((span, ExprKind::Box(expr)))
645     }
646
647     fn is_mistaken_not_ident_negation(&self) -> bool {
648         let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
649             // These tokens can start an expression after `!`, but
650             // can't continue an expression after an ident
651             token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
652             token::Literal(..) | token::Pound => true,
653             _ => t.is_whole_expr(),
654         };
655         self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr)
656     }
657
658     /// Recover on `not expr` in favor of `!expr`.
659     fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
660         // Emit the error...
661         let negated_token = self.look_ahead(1, |t| t.clone());
662
663         let sub_diag = if negated_token.is_numeric_lit() {
664             NotAsNegationOperatorSub::SuggestNotBitwise
665         } else if negated_token.is_bool_lit() {
666             NotAsNegationOperatorSub::SuggestNotLogical
667         } else {
668             NotAsNegationOperatorSub::SuggestNotDefault
669         };
670
671         self.sess.emit_err(NotAsNegationOperator {
672             negated: negated_token.span,
673             negated_desc: super::token_descr(&negated_token),
674             // Span the `not` plus trailing whitespace to avoid
675             // trailing whitespace after the `!` in our suggestion
676             sub: sub_diag(
677                 self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
678             ),
679         });
680
681         // ...and recover!
682         self.parse_unary_expr(lo, UnOp::Not)
683     }
684
685     /// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
686     fn interpolated_or_expr_span(
687         &self,
688         expr: PResult<'a, P<Expr>>,
689     ) -> PResult<'a, (Span, P<Expr>)> {
690         expr.map(|e| {
691             (
692                 match self.prev_token.kind {
693                     TokenKind::Interpolated(..) => self.prev_token.span,
694                     _ => e.span,
695                 },
696                 e,
697             )
698         })
699     }
700
701     fn parse_assoc_op_cast(
702         &mut self,
703         lhs: P<Expr>,
704         lhs_span: Span,
705         expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
706     ) -> PResult<'a, P<Expr>> {
707         let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
708             this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, rhs.span), expr_kind(lhs, rhs))
709         };
710
711         // Save the state of the parser before parsing type normally, in case there is a
712         // LessThan comparison after this cast.
713         let parser_snapshot_before_type = self.clone();
714         let cast_expr = match self.parse_as_cast_ty() {
715             Ok(rhs) => mk_expr(self, lhs, rhs),
716             Err(type_err) => {
717                 if !self.may_recover() {
718                     return Err(type_err);
719                 }
720
721                 // Rewind to before attempting to parse the type with generics, to recover
722                 // from situations like `x as usize < y` in which we first tried to parse
723                 // `usize < y` as a type with generic arguments.
724                 let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type);
725
726                 // Check for typo of `'a: loop { break 'a }` with a missing `'`.
727                 match (&lhs.kind, &self.token.kind) {
728                     (
729                         // `foo: `
730                         ExprKind::Path(None, ast::Path { segments, .. }),
731                         TokenKind::Ident(kw::For | kw::Loop | kw::While, false),
732                     ) if segments.len() == 1 => {
733                         let snapshot = self.create_snapshot_for_diagnostic();
734                         let label = Label {
735                             ident: Ident::from_str_and_span(
736                                 &format!("'{}", segments[0].ident),
737                                 segments[0].ident.span,
738                             ),
739                         };
740                         match self.parse_labeled_expr(label, false) {
741                             Ok(expr) => {
742                                 type_err.cancel();
743                                 self.sess.emit_err(MalformedLoopLabel {
744                                     span: label.ident.span,
745                                     correct_label: label.ident,
746                                 });
747                                 return Ok(expr);
748                             }
749                             Err(err) => {
750                                 err.cancel();
751                                 self.restore_snapshot(snapshot);
752                             }
753                         }
754                     }
755                     _ => {}
756                 }
757
758                 match self.parse_path(PathStyle::Expr) {
759                     Ok(path) => {
760                         let span_after_type = parser_snapshot_after_type.token.span;
761                         let expr = mk_expr(
762                             self,
763                             lhs,
764                             self.mk_ty(path.span, TyKind::Path(None, path.clone())),
765                         );
766
767                         let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
768                         let suggestion = ComparisonOrShiftInterpretedAsGenericSugg {
769                             left: expr.span.shrink_to_lo(),
770                             right: expr.span.shrink_to_hi(),
771                         };
772
773                         match self.token.kind {
774                             token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric {
775                                 comparison: self.token.span,
776                                 r#type: path,
777                                 args: args_span,
778                                 suggestion,
779                             }),
780                             token::BinOp(token::Shl) => {
781                                 self.sess.emit_err(ShiftInterpretedAsGeneric {
782                                     shift: self.token.span,
783                                     r#type: path,
784                                     args: args_span,
785                                     suggestion,
786                                 })
787                             }
788                             _ => {
789                                 // We can end up here even without `<` being the next token, for
790                                 // example because `parse_ty_no_plus` returns `Err` on keywords,
791                                 // but `parse_path` returns `Ok` on them due to error recovery.
792                                 // Return original error and parser state.
793                                 *self = parser_snapshot_after_type;
794                                 return Err(type_err);
795                             }
796                         };
797
798                         // Successfully parsed the type path leaving a `<` yet to parse.
799                         type_err.cancel();
800
801                         // Keep `x as usize` as an expression in AST and continue parsing.
802                         expr
803                     }
804                     Err(path_err) => {
805                         // Couldn't parse as a path, return original error and parser state.
806                         path_err.cancel();
807                         *self = parser_snapshot_after_type;
808                         return Err(type_err);
809                     }
810                 }
811             }
812         };
813
814         self.parse_and_disallow_postfix_after_cast(cast_expr)
815     }
816
817     /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast,
818     /// then emits an error and returns the newly parsed tree.
819     /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`.
820     fn parse_and_disallow_postfix_after_cast(
821         &mut self,
822         cast_expr: P<Expr>,
823     ) -> PResult<'a, P<Expr>> {
824         let span = cast_expr.span;
825         let (cast_kind, maybe_ascription_span) =
826             if let ExprKind::Type(ascripted_expr, _) = &cast_expr.kind {
827                 ("type ascription", Some(ascripted_expr.span.shrink_to_hi().with_hi(span.hi())))
828             } else {
829                 ("cast", None)
830             };
831
832         let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
833
834         // Check if an illegal postfix operator has been added after the cast.
835         // If the resulting expression is not a cast, it is an illegal postfix operator.
836         if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) {
837             let msg = format!(
838                 "{cast_kind} cannot be followed by {}",
839                 match with_postfix.kind {
840                     ExprKind::Index(_, _) => "indexing",
841                     ExprKind::Try(_) => "`?`",
842                     ExprKind::Field(_, _) => "a field access",
843                     ExprKind::MethodCall(_) => "a method call",
844                     ExprKind::Call(_, _) => "a function call",
845                     ExprKind::Await(_) => "`.await`",
846                     ExprKind::Err => return Ok(with_postfix),
847                     _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"),
848                 }
849             );
850             let mut err = self.struct_span_err(span, &msg);
851
852             let suggest_parens = |err: &mut Diagnostic| {
853                 let suggestions = vec![
854                     (span.shrink_to_lo(), "(".to_string()),
855                     (span.shrink_to_hi(), ")".to_string()),
856                 ];
857                 err.multipart_suggestion(
858                     "try surrounding the expression in parentheses",
859                     suggestions,
860                     Applicability::MachineApplicable,
861                 );
862             };
863
864             // If type ascription is "likely an error", the user will already be getting a useful
865             // help message, and doesn't need a second.
866             if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) {
867                 self.maybe_annotate_with_ascription(&mut err, false);
868             } else if let Some(ascription_span) = maybe_ascription_span {
869                 let is_nightly = self.sess.unstable_features.is_nightly_build();
870                 if is_nightly {
871                     suggest_parens(&mut err);
872                 }
873                 err.span_suggestion(
874                     ascription_span,
875                     &format!(
876                         "{}remove the type ascription",
877                         if is_nightly { "alternatively, " } else { "" }
878                     ),
879                     "",
880                     if is_nightly {
881                         Applicability::MaybeIncorrect
882                     } else {
883                         Applicability::MachineApplicable
884                     },
885                 );
886             } else {
887                 suggest_parens(&mut err);
888             }
889             err.emit();
890         };
891         Ok(with_postfix)
892     }
893
894     fn parse_assoc_op_ascribe(&mut self, lhs: P<Expr>, lhs_span: Span) -> PResult<'a, P<Expr>> {
895         let maybe_path = self.could_ascription_be_path(&lhs.kind);
896         self.last_type_ascription = Some((self.prev_token.span, maybe_path));
897         let lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
898         self.sess.gated_spans.gate(sym::type_ascription, lhs.span);
899         Ok(lhs)
900     }
901
902     /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
903     fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
904         self.expect_and()?;
905         let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
906         let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
907         let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
908         let expr = self.parse_prefix_expr(None);
909         let (hi, expr) = self.interpolated_or_expr_span(expr)?;
910         let span = lo.to(hi);
911         if let Some(lt) = lifetime {
912             self.error_remove_borrow_lifetime(span, lt.ident.span);
913         }
914         Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
915     }
916
917     fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
918         self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
919     }
920
921     /// Parse `mut?` or `raw [ const | mut ]`.
922     fn parse_borrow_modifiers(&mut self, lo: Span) -> (ast::BorrowKind, ast::Mutability) {
923         if self.check_keyword(kw::Raw) && self.look_ahead(1, Token::is_mutability) {
924             // `raw [ const | mut ]`.
925             let found_raw = self.eat_keyword(kw::Raw);
926             assert!(found_raw);
927             let mutability = self.parse_const_or_mut().unwrap();
928             self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span));
929             (ast::BorrowKind::Raw, mutability)
930         } else {
931             // `mut?`
932             (ast::BorrowKind::Ref, self.parse_mutability())
933         }
934     }
935
936     /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
937     fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
938         let attrs = self.parse_or_use_outer_attributes(attrs)?;
939         self.collect_tokens_for_expr(attrs, |this, attrs| {
940             let base = this.parse_bottom_expr();
941             let (span, base) = this.interpolated_or_expr_span(base)?;
942             this.parse_dot_or_call_expr_with(base, span, attrs)
943         })
944     }
945
946     pub(super) fn parse_dot_or_call_expr_with(
947         &mut self,
948         e0: P<Expr>,
949         lo: Span,
950         mut attrs: ast::AttrVec,
951     ) -> PResult<'a, P<Expr>> {
952         // Stitch the list of outer attributes onto the return value.
953         // A little bit ugly, but the best way given the current code
954         // structure
955         let res = self.parse_dot_or_call_expr_with_(e0, lo);
956         if attrs.is_empty() {
957             res
958         } else {
959             res.map(|expr| {
960                 expr.map(|mut expr| {
961                     attrs.extend(expr.attrs);
962                     expr.attrs = attrs;
963                     expr
964                 })
965             })
966         }
967     }
968
969     fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
970         loop {
971             let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
972                 // we are using noexpect here because we don't expect a `?` directly after a `return`
973                 // which could be suggested otherwise
974                 self.eat_noexpect(&token::Question)
975             } else {
976                 self.eat(&token::Question)
977             };
978             if has_question {
979                 // `expr?`
980                 e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
981                 continue;
982             }
983             let has_dot = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
984                 // we are using noexpect here because we don't expect a `.` directly after a `return`
985                 // which could be suggested otherwise
986                 self.eat_noexpect(&token::Dot)
987             } else {
988                 self.eat(&token::Dot)
989             };
990             if has_dot {
991                 // expr.f
992                 e = self.parse_dot_suffix_expr(lo, e)?;
993                 continue;
994             }
995             if self.expr_is_complete(&e) {
996                 return Ok(e);
997             }
998             e = match self.token.kind {
999                 token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
1000                 token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
1001                 _ => return Ok(e),
1002             }
1003         }
1004     }
1005
1006     fn look_ahead_type_ascription_as_field(&mut self) -> bool {
1007         self.look_ahead(1, |t| t.is_ident())
1008             && self.look_ahead(2, |t| t == &token::Colon)
1009             && self.look_ahead(3, |t| t.can_begin_expr())
1010     }
1011
1012     fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
1013         match self.token.uninterpolate().kind {
1014             token::Ident(..) => self.parse_dot_suffix(base, lo),
1015             token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
1016                 Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None))
1017             }
1018             token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
1019                 Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix))
1020             }
1021             _ => {
1022                 self.error_unexpected_after_dot();
1023                 Ok(base)
1024             }
1025         }
1026     }
1027
1028     fn error_unexpected_after_dot(&self) {
1029         // FIXME Could factor this out into non_fatal_unexpected or something.
1030         let actual = pprust::token_to_string(&self.token);
1031         self.struct_span_err(self.token.span, &format!("unexpected token: `{actual}`")).emit();
1032     }
1033
1034     // We need an identifier or integer, but the next token is a float.
1035     // Break the float into components to extract the identifier or integer.
1036     // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2
1037     // parts unless those parts are processed immediately. `TokenCursor` should either
1038     // support pushing "future tokens" (would be also helpful to `break_and_eat`), or
1039     // we should break everything including floats into more basic proc-macro style
1040     // tokens in the lexer (probably preferable).
1041     fn parse_tuple_field_access_expr_float(
1042         &mut self,
1043         lo: Span,
1044         base: P<Expr>,
1045         float: Symbol,
1046         suffix: Option<Symbol>,
1047     ) -> P<Expr> {
1048         #[derive(Debug)]
1049         enum FloatComponent {
1050             IdentLike(String),
1051             Punct(char),
1052         }
1053         use FloatComponent::*;
1054
1055         let float_str = float.as_str();
1056         let mut components = Vec::new();
1057         let mut ident_like = String::new();
1058         for c in float_str.chars() {
1059             if c == '_' || c.is_ascii_alphanumeric() {
1060                 ident_like.push(c);
1061             } else if matches!(c, '.' | '+' | '-') {
1062                 if !ident_like.is_empty() {
1063                     components.push(IdentLike(mem::take(&mut ident_like)));
1064                 }
1065                 components.push(Punct(c));
1066             } else {
1067                 panic!("unexpected character in a float token: {:?}", c)
1068             }
1069         }
1070         if !ident_like.is_empty() {
1071             components.push(IdentLike(ident_like));
1072         }
1073
1074         // With proc macros the span can refer to anything, the source may be too short,
1075         // or too long, or non-ASCII. It only makes sense to break our span into components
1076         // if its underlying text is identical to our float literal.
1077         let span = self.token.span;
1078         let can_take_span_apart =
1079             || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref();
1080
1081         match &*components {
1082             // 1e2
1083             [IdentLike(i)] => {
1084                 self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None)
1085             }
1086             // 1.
1087             [IdentLike(i), Punct('.')] => {
1088                 let (ident_span, dot_span) = if can_take_span_apart() {
1089                     let (span, ident_len) = (span.data(), BytePos::from_usize(i.len()));
1090                     let ident_span = span.with_hi(span.lo + ident_len);
1091                     let dot_span = span.with_lo(span.lo + ident_len);
1092                     (ident_span, dot_span)
1093                 } else {
1094                     (span, span)
1095                 };
1096                 assert!(suffix.is_none());
1097                 let symbol = Symbol::intern(&i);
1098                 self.token = Token::new(token::Ident(symbol, false), ident_span);
1099                 let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
1100                 self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token))
1101             }
1102             // 1.2 | 1.2e3
1103             [IdentLike(i1), Punct('.'), IdentLike(i2)] => {
1104                 let (ident1_span, dot_span, ident2_span) = if can_take_span_apart() {
1105                     let (span, ident1_len) = (span.data(), BytePos::from_usize(i1.len()));
1106                     let ident1_span = span.with_hi(span.lo + ident1_len);
1107                     let dot_span = span
1108                         .with_lo(span.lo + ident1_len)
1109                         .with_hi(span.lo + ident1_len + BytePos(1));
1110                     let ident2_span = self.token.span.with_lo(span.lo + ident1_len + BytePos(1));
1111                     (ident1_span, dot_span, ident2_span)
1112                 } else {
1113                     (span, span, span)
1114                 };
1115                 let symbol1 = Symbol::intern(&i1);
1116                 self.token = Token::new(token::Ident(symbol1, false), ident1_span);
1117                 // This needs to be `Spacing::Alone` to prevent regressions.
1118                 // See issue #76399 and PR #76285 for more details
1119                 let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
1120                 let base1 =
1121                     self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1));
1122                 let symbol2 = Symbol::intern(&i2);
1123                 let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
1124                 self.bump_with((next_token2, self.token_spacing)); // `.`
1125                 self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None)
1126             }
1127             // 1e+ | 1e- (recovered)
1128             [IdentLike(_), Punct('+' | '-')] |
1129             // 1e+2 | 1e-2
1130             [IdentLike(_), Punct('+' | '-'), IdentLike(_)] |
1131             // 1.2e+ | 1.2e-
1132             [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] |
1133             // 1.2e+3 | 1.2e-3
1134             [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => {
1135                 // See the FIXME about `TokenCursor` above.
1136                 self.error_unexpected_after_dot();
1137                 base
1138             }
1139             _ => panic!("unexpected components in a float token: {:?}", components),
1140         }
1141     }
1142
1143     fn parse_tuple_field_access_expr(
1144         &mut self,
1145         lo: Span,
1146         base: P<Expr>,
1147         field: Symbol,
1148         suffix: Option<Symbol>,
1149         next_token: Option<(Token, Spacing)>,
1150     ) -> P<Expr> {
1151         match next_token {
1152             Some(next_token) => self.bump_with(next_token),
1153             None => self.bump(),
1154         }
1155         let span = self.prev_token.span;
1156         let field = ExprKind::Field(base, Ident::new(field, span));
1157         if let Some(suffix) = suffix {
1158             self.expect_no_tuple_index_suffix(span, suffix);
1159         }
1160         self.mk_expr(lo.to(span), field)
1161     }
1162
1163     /// Parse a function call expression, `expr(...)`.
1164     fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
1165         let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
1166             && self.look_ahead_type_ascription_as_field()
1167         {
1168             Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
1169         } else {
1170             None
1171         };
1172         let open_paren = self.token.span;
1173
1174         let mut seq = self
1175             .parse_paren_expr_seq()
1176             .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
1177         if let Some(expr) =
1178             self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
1179         {
1180             return expr;
1181         }
1182         self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq)
1183     }
1184
1185     /// If we encounter a parser state that looks like the user has written a `struct` literal with
1186     /// parentheses instead of braces, recover the parser state and provide suggestions.
1187     #[instrument(skip(self, seq, snapshot), level = "trace")]
1188     fn maybe_recover_struct_lit_bad_delims(
1189         &mut self,
1190         lo: Span,
1191         open_paren: Span,
1192         seq: &mut PResult<'a, P<Expr>>,
1193         snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
1194     ) -> Option<P<Expr>> {
1195         if !self.may_recover() {
1196             return None;
1197         }
1198
1199         match (seq.as_mut(), snapshot) {
1200             (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
1201                 snapshot.bump(); // `(`
1202                 match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) {
1203                     Ok((fields, ..))
1204                         if snapshot.eat(&token::CloseDelim(Delimiter::Parenthesis)) =>
1205                     {
1206                         // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
1207                         // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
1208                         self.restore_snapshot(snapshot);
1209                         let close_paren = self.prev_token.span;
1210                         let span = lo.to(self.prev_token.span);
1211                         if !fields.is_empty() {
1212                             let mut replacement_err = ParenthesesWithStructFields {
1213                                 span,
1214                                 r#type: path,
1215                                 braces_for_struct: BracesForStructLiteral {
1216                                     first: open_paren,
1217                                     second: close_paren,
1218                                 },
1219                                 no_fields_for_fn: NoFieldsForFnCall {
1220                                     fields: fields
1221                                         .into_iter()
1222                                         .map(|field| field.span.until(field.expr.span))
1223                                         .collect(),
1224                                 },
1225                             }
1226                             .into_diagnostic(&self.sess.span_diagnostic);
1227                             replacement_err.emit();
1228
1229                             let old_err = mem::replace(err, replacement_err);
1230                             old_err.cancel();
1231                         } else {
1232                             err.emit();
1233                         }
1234                         return Some(self.mk_expr_err(span));
1235                     }
1236                     Ok(_) => {}
1237                     Err(mut err) => {
1238                         err.emit();
1239                     }
1240                 }
1241             }
1242             _ => {}
1243         }
1244         None
1245     }
1246
1247     /// Parse an indexing expression `expr[...]`.
1248     fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
1249         let prev_span = self.prev_token.span;
1250         let open_delim_span = self.token.span;
1251         self.bump(); // `[`
1252         let index = self.parse_expr()?;
1253         self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
1254         self.expect(&token::CloseDelim(Delimiter::Bracket))?;
1255         Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index)))
1256     }
1257
1258     /// Assuming we have just parsed `.`, continue parsing into an expression.
1259     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
1260         if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) {
1261             return Ok(self.mk_await_expr(self_arg, lo));
1262         }
1263
1264         let fn_span_lo = self.token.span;
1265         let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
1266         self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
1267         self.check_turbofish_missing_angle_brackets(&mut seg);
1268
1269         if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
1270             // Method call `expr.f()`
1271             let args = self.parse_paren_expr_seq()?;
1272             let fn_span = fn_span_lo.to(self.prev_token.span);
1273             let span = lo.to(self.prev_token.span);
1274             Ok(self.mk_expr(
1275                 span,
1276                 ExprKind::MethodCall(Box::new(ast::MethodCall {
1277                     seg,
1278                     receiver: self_arg,
1279                     args,
1280                     span: fn_span,
1281                 })),
1282             ))
1283         } else {
1284             // Field access `expr.f`
1285             if let Some(args) = seg.args {
1286                 self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
1287             }
1288
1289             let span = lo.to(self.prev_token.span);
1290             Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
1291         }
1292     }
1293
1294     /// At the bottom (top?) of the precedence hierarchy,
1295     /// Parses things like parenthesized exprs, macros, `return`, etc.
1296     ///
1297     /// N.B., this does not parse outer attributes, and is private because it only works
1298     /// correctly if called from `parse_dot_or_call_expr()`.
1299     fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
1300         maybe_recover_from_interpolated_ty_qpath!(self, true);
1301         maybe_whole_expr!(self);
1302
1303         // Outer attributes are already parsed and will be
1304         // added to the return value after the fact.
1305
1306         // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
1307         let lo = self.token.span;
1308         if let token::Literal(_) = self.token.kind {
1309             // This match arm is a special-case of the `_` match arm below and
1310             // could be removed without changing functionality, but it's faster
1311             // to have it here, especially for programs with large constants.
1312             self.parse_lit_expr()
1313         } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
1314             self.parse_tuple_parens_expr()
1315         } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
1316             self.parse_block_expr(None, lo, BlockCheckMode::Default)
1317         } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
1318             self.parse_closure_expr().map_err(|mut err| {
1319                 // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
1320                 // then suggest parens around the lhs.
1321                 if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
1322                     err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
1323                 }
1324                 err
1325             })
1326         } else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
1327             self.parse_array_or_repeat_expr(Delimiter::Bracket)
1328         } else if self.check_path() {
1329             self.parse_path_start_expr()
1330         } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
1331             self.parse_closure_expr()
1332         } else if self.eat_keyword(kw::If) {
1333             self.parse_if_expr()
1334         } else if self.check_keyword(kw::For) {
1335             if self.choose_generics_over_qpath(1) {
1336                 self.parse_closure_expr()
1337             } else {
1338                 assert!(self.eat_keyword(kw::For));
1339                 self.parse_for_expr(None, self.prev_token.span)
1340             }
1341         } else if self.eat_keyword(kw::While) {
1342             self.parse_while_expr(None, self.prev_token.span)
1343         } else if let Some(label) = self.eat_label() {
1344             self.parse_labeled_expr(label, true)
1345         } else if self.eat_keyword(kw::Loop) {
1346             let sp = self.prev_token.span;
1347             self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
1348                 err.span_label(sp, "while parsing this `loop` expression");
1349                 err
1350             })
1351         } else if self.eat_keyword(kw::Continue) {
1352             let kind = ExprKind::Continue(self.eat_label());
1353             Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
1354         } else if self.eat_keyword(kw::Match) {
1355             let match_sp = self.prev_token.span;
1356             self.parse_match_expr().map_err(|mut err| {
1357                 err.span_label(match_sp, "while parsing this `match` expression");
1358                 err
1359             })
1360         } else if self.eat_keyword(kw::Unsafe) {
1361             let sp = self.prev_token.span;
1362             self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
1363                 |mut err| {
1364                     err.span_label(sp, "while parsing this `unsafe` expression");
1365                     err
1366                 },
1367             )
1368         } else if self.check_inline_const(0) {
1369             self.parse_const_block(lo.to(self.token.span), false)
1370         } else if self.may_recover() && self.is_do_catch_block() {
1371             self.recover_do_catch()
1372         } else if self.is_try_block() {
1373             self.expect_keyword(kw::Try)?;
1374             self.parse_try_block(lo)
1375         } else if self.eat_keyword(kw::Return) {
1376             self.parse_return_expr()
1377         } else if self.eat_keyword(kw::Break) {
1378             self.parse_break_expr()
1379         } else if self.eat_keyword(kw::Yield) {
1380             self.parse_yield_expr()
1381         } else if self.is_do_yeet() {
1382             self.parse_yeet_expr()
1383         } else if self.check_keyword(kw::Let) {
1384             self.parse_let_expr()
1385         } else if self.eat_keyword(kw::Underscore) {
1386             Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
1387         } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
1388             // Don't complain about bare semicolons after unclosed braces
1389             // recovery in order to keep the error count down. Fixing the
1390             // delimiters will possibly also fix the bare semicolon found in
1391             // expression context. For example, silence the following error:
1392             //
1393             //     error: expected expression, found `;`
1394             //      --> file.rs:2:13
1395             //       |
1396             //     2 |     foo(bar(;
1397             //       |             ^ expected expression
1398             self.bump();
1399             Ok(self.mk_expr_err(self.token.span))
1400         } else if self.token.uninterpolated_span().rust_2018() {
1401             // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
1402             if self.check_keyword(kw::Async) {
1403                 if self.is_async_block() {
1404                     // Check for `async {` and `async move {`.
1405                     self.parse_async_block()
1406                 } else {
1407                     self.parse_closure_expr()
1408                 }
1409             } else if self.eat_keyword(kw::Await) {
1410                 self.recover_incorrect_await_syntax(lo, self.prev_token.span)
1411             } else {
1412                 self.parse_lit_expr()
1413             }
1414         } else {
1415             self.parse_lit_expr()
1416         }
1417     }
1418
1419     fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
1420         let lo = self.token.span;
1421         match self.parse_opt_token_lit() {
1422             Some((token_lit, _)) => {
1423                 let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit));
1424                 self.maybe_recover_from_bad_qpath(expr)
1425             }
1426             None => self.try_macro_suggestion(),
1427         }
1428     }
1429
1430     fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
1431         let lo = self.token.span;
1432         self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
1433         let (es, trailing_comma) = match self.parse_seq_to_end(
1434             &token::CloseDelim(Delimiter::Parenthesis),
1435             SeqSep::trailing_allowed(token::Comma),
1436             |p| p.parse_expr_catch_underscore(),
1437         ) {
1438             Ok(x) => x,
1439             Err(err) => {
1440                 return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err)));
1441             }
1442         };
1443         let kind = if es.len() == 1 && !trailing_comma {
1444             // `(e)` is parenthesized `e`.
1445             ExprKind::Paren(es.into_iter().next().unwrap())
1446         } else {
1447             // `(e,)` is a tuple with only one field, `e`.
1448             ExprKind::Tup(es)
1449         };
1450         let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1451         self.maybe_recover_from_bad_qpath(expr)
1452     }
1453
1454     fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
1455         let lo = self.token.span;
1456         self.bump(); // `[` or other open delim
1457
1458         let close = &token::CloseDelim(close_delim);
1459         let kind = if self.eat(close) {
1460             // Empty vector
1461             ExprKind::Array(Vec::new())
1462         } else {
1463             // Non-empty vector
1464             let first_expr = self.parse_expr()?;
1465             if self.eat(&token::Semi) {
1466                 // Repeating array syntax: `[ 0; 512 ]`
1467                 let count = self.parse_anon_const_expr()?;
1468                 self.expect(close)?;
1469                 ExprKind::Repeat(first_expr, count)
1470             } else if self.eat(&token::Comma) {
1471                 // Vector with two or more elements.
1472                 let sep = SeqSep::trailing_allowed(token::Comma);
1473                 let (remaining_exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?;
1474                 let mut exprs = vec![first_expr];
1475                 exprs.extend(remaining_exprs);
1476                 ExprKind::Array(exprs)
1477             } else {
1478                 // Vector with one element
1479                 self.expect(close)?;
1480                 ExprKind::Array(vec![first_expr])
1481             }
1482         };
1483         let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1484         self.maybe_recover_from_bad_qpath(expr)
1485     }
1486
1487     fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
1488         let (qself, path) = if self.eat_lt() {
1489             let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
1490             (Some(qself), path)
1491         } else {
1492             (None, self.parse_path(PathStyle::Expr)?)
1493         };
1494
1495         // `!`, as an operator, is prefix, so we know this isn't that.
1496         let (span, kind) = if self.eat(&token::Not) {
1497             // MACRO INVOCATION expression
1498             if qself.is_some() {
1499                 self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
1500             }
1501             let lo = path.span;
1502             let mac = P(MacCall {
1503                 path,
1504                 args: self.parse_delim_args()?,
1505                 prior_type_ascription: self.last_type_ascription,
1506             });
1507             (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
1508         } else if self.check(&token::OpenDelim(Delimiter::Brace)) &&
1509             let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) {
1510                 if qself.is_some() {
1511                     self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
1512                 }
1513                 return expr;
1514         } else {
1515             (path.span, ExprKind::Path(qself, path))
1516         };
1517
1518         let expr = self.mk_expr(span, kind);
1519         self.maybe_recover_from_bad_qpath(expr)
1520     }
1521
1522     /// Parse `'label: $expr`. The label is already parsed.
1523     fn parse_labeled_expr(
1524         &mut self,
1525         label_: Label,
1526         mut consume_colon: bool,
1527     ) -> PResult<'a, P<Expr>> {
1528         let lo = label_.ident.span;
1529         let label = Some(label_);
1530         let ate_colon = self.eat(&token::Colon);
1531         let expr = if self.eat_keyword(kw::While) {
1532             self.parse_while_expr(label, lo)
1533         } else if self.eat_keyword(kw::For) {
1534             self.parse_for_expr(label, lo)
1535         } else if self.eat_keyword(kw::Loop) {
1536             self.parse_loop_expr(label, lo)
1537         } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
1538             || self.token.is_whole_block()
1539         {
1540             self.parse_block_expr(label, lo, BlockCheckMode::Default)
1541         } else if !ate_colon
1542             && self.may_recover()
1543             && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
1544                 || self.token.is_op())
1545         {
1546             let lit = self.recover_unclosed_char(label_.ident, |self_| {
1547                 self_.sess.create_err(UnexpectedTokenAfterLabel {
1548                     span: self_.token.span,
1549                     remove_label: None,
1550                     enclose_in_block: None,
1551                 })
1552             });
1553             consume_colon = false;
1554             Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit)))
1555         } else if !ate_colon
1556             && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
1557         {
1558             // We're probably inside of a `Path<'a>` that needs a turbofish
1559             self.sess.emit_err(UnexpectedTokenAfterLabel {
1560                 span: self.token.span,
1561                 remove_label: None,
1562                 enclose_in_block: None,
1563             });
1564             consume_colon = false;
1565             Ok(self.mk_expr_err(lo))
1566         } else {
1567             let mut err = UnexpectedTokenAfterLabel {
1568                 span: self.token.span,
1569                 remove_label: None,
1570                 enclose_in_block: None,
1571             };
1572
1573             // Continue as an expression in an effort to recover on `'label: non_block_expr`.
1574             let expr = self.parse_expr().map(|expr| {
1575                 let span = expr.span;
1576
1577                 let found_labeled_breaks = {
1578                     struct FindLabeledBreaksVisitor(bool);
1579
1580                     impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
1581                         fn visit_expr_post(&mut self, ex: &'ast Expr) {
1582                             if let ExprKind::Break(Some(_label), _) = ex.kind {
1583                                 self.0 = true;
1584                             }
1585                         }
1586                     }
1587
1588                     let mut vis = FindLabeledBreaksVisitor(false);
1589                     vis.visit_expr(&expr);
1590                     vis.0
1591                 };
1592
1593                 // Suggestion involves adding a (as of time of writing this, unstable) labeled block.
1594                 //
1595                 // If there are no breaks that may use this label, suggest removing the label and
1596                 // recover to the unmodified expression.
1597                 if !found_labeled_breaks {
1598                     err.remove_label = Some(lo.until(span));
1599
1600                     return expr;
1601                 }
1602
1603                 err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg {
1604                     left: span.shrink_to_lo(),
1605                     right: span.shrink_to_hi(),
1606                 });
1607
1608                 // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
1609                 let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
1610                 let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span);
1611                 self.mk_expr(span, ExprKind::Block(blk, label))
1612             });
1613
1614             self.sess.emit_err(err);
1615             expr
1616         }?;
1617
1618         if !ate_colon && consume_colon {
1619             self.sess.emit_err(RequireColonAfterLabeledExpression {
1620                 span: expr.span,
1621                 label: lo,
1622                 label_end: lo.shrink_to_hi(),
1623             });
1624         }
1625
1626         Ok(expr)
1627     }
1628
1629     /// Emit an error when a char is parsed as a lifetime because of a missing quote
1630     pub(super) fn recover_unclosed_char(
1631         &self,
1632         lifetime: Ident,
1633         err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
1634     ) -> ast::MetaItemLit {
1635         if let Some(mut diag) =
1636             self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
1637         {
1638             diag.span_suggestion_verbose(
1639                 lifetime.span.shrink_to_hi(),
1640                 "add `'` to close the char literal",
1641                 "'",
1642                 Applicability::MaybeIncorrect,
1643             )
1644             .emit();
1645         } else {
1646             err(self)
1647                 .span_suggestion_verbose(
1648                     lifetime.span.shrink_to_hi(),
1649                     "add `'` to close the char literal",
1650                     "'",
1651                     Applicability::MaybeIncorrect,
1652                 )
1653                 .emit();
1654         }
1655         let name = lifetime.without_first_quote().name;
1656         ast::MetaItemLit {
1657             token_lit: token::Lit::new(token::LitKind::Char, name, None),
1658             kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
1659             span: lifetime.span,
1660         }
1661     }
1662
1663     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
1664     fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
1665         let lo = self.token.span;
1666
1667         self.bump(); // `do`
1668         self.bump(); // `catch`
1669
1670         let span = lo.to(self.prev_token.span);
1671         self.sess.emit_err(DoCatchSyntaxRemoved { span });
1672
1673         self.parse_try_block(lo)
1674     }
1675
1676     /// Parse an expression if the token can begin one.
1677     fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> {
1678         Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None })
1679     }
1680
1681     /// Parse `"return" expr?`.
1682     fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
1683         let lo = self.prev_token.span;
1684         let kind = ExprKind::Ret(self.parse_expr_opt()?);
1685         let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1686         self.maybe_recover_from_bad_qpath(expr)
1687     }
1688
1689     /// Parse `"do" "yeet" expr?`.
1690     fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
1691         let lo = self.token.span;
1692
1693         self.bump(); // `do`
1694         self.bump(); // `yeet`
1695
1696         let kind = ExprKind::Yeet(self.parse_expr_opt()?);
1697
1698         let span = lo.to(self.prev_token.span);
1699         self.sess.gated_spans.gate(sym::yeet_expr, span);
1700         let expr = self.mk_expr(span, kind);
1701         self.maybe_recover_from_bad_qpath(expr)
1702     }
1703
1704     /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten.
1705     /// If the label is followed immediately by a `:` token, the label and `:` are
1706     /// parsed as part of the expression (i.e. a labeled loop). The language team has
1707     /// decided in #87026 to require parentheses as a visual aid to avoid confusion if
1708     /// the break expression of an unlabeled break is a labeled loop (as in
1709     /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
1710     /// expression only gets a warning for compatibility reasons; and a labeled break
1711     /// with a labeled loop does not even get a warning because there is no ambiguity.
1712     fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
1713         let lo = self.prev_token.span;
1714         let mut label = self.eat_label();
1715         let kind = if label.is_some() && self.token == token::Colon {
1716             // The value expression can be a labeled loop, see issue #86948, e.g.:
1717             // `loop { break 'label: loop { break 'label 42; }; }`
1718             let lexpr = self.parse_labeled_expr(label.take().unwrap(), true)?;
1719             self.sess.emit_err(LabeledLoopInBreak {
1720                 span: lexpr.span,
1721                 sub: WrapExpressionInParentheses {
1722                     left: lexpr.span.shrink_to_lo(),
1723                     right: lexpr.span.shrink_to_hi(),
1724                 },
1725             });
1726             Some(lexpr)
1727         } else if self.token != token::OpenDelim(Delimiter::Brace)
1728             || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
1729         {
1730             let expr = self.parse_expr_opt()?;
1731             if let Some(expr) = &expr {
1732                 if label.is_some()
1733                     && matches!(
1734                         expr.kind,
1735                         ExprKind::While(_, _, None)
1736                             | ExprKind::ForLoop(_, _, _, None)
1737                             | ExprKind::Loop(_, None, _)
1738                             | ExprKind::Block(_, None)
1739                     )
1740                 {
1741                     self.sess.buffer_lint_with_diagnostic(
1742                         BREAK_WITH_LABEL_AND_LOOP,
1743                         lo.to(expr.span),
1744                         ast::CRATE_NODE_ID,
1745                         "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression",
1746                         BuiltinLintDiagnostics::BreakWithLabelAndLoop(expr.span),
1747                     );
1748                 }
1749             }
1750             expr
1751         } else {
1752             None
1753         };
1754         let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind));
1755         self.maybe_recover_from_bad_qpath(expr)
1756     }
1757
1758     /// Parse `"yield" expr?`.
1759     fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
1760         let lo = self.prev_token.span;
1761         let kind = ExprKind::Yield(self.parse_expr_opt()?);
1762         let span = lo.to(self.prev_token.span);
1763         self.sess.gated_spans.gate(sym::generators, span);
1764         let expr = self.mk_expr(span, kind);
1765         self.maybe_recover_from_bad_qpath(expr)
1766     }
1767
1768     /// Returns a string literal if the next token is a string literal.
1769     /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
1770     /// and returns `None` if the next token is not literal at all.
1771     pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
1772         match self.parse_opt_meta_item_lit() {
1773             Some(lit) => match lit.kind {
1774                 ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
1775                     style,
1776                     symbol: lit.token_lit.symbol,
1777                     suffix: lit.token_lit.suffix,
1778                     span: lit.span,
1779                     symbol_unescaped,
1780                 }),
1781                 _ => Err(Some(lit)),
1782             },
1783             None => Err(None),
1784         }
1785     }
1786
1787     fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> {
1788         if let token::Interpolated(inner) = &self.token.kind {
1789             let expr = match inner.as_ref() {
1790                 token::NtExpr(expr) => Some(expr),
1791                 token::NtLiteral(expr) => Some(expr),
1792                 _ => None,
1793             };
1794             if let Some(expr) = expr {
1795                 if matches!(expr.kind, ExprKind::Err) {
1796                     let mut err = InvalidInterpolatedExpression { span: self.token.span }
1797                         .into_diagnostic(&self.sess.span_diagnostic);
1798                     err.downgrade_to_delayed_bug();
1799                     return Err(err);
1800                 }
1801             }
1802         }
1803         let token = self.token.clone();
1804         let err = |self_: &Self| {
1805             let msg = format!("unexpected token: {}", super::token_descr(&token));
1806             self_.struct_span_err(token.span, &msg)
1807         };
1808         // On an error path, eagerly consider a lifetime to be an unclosed character lit
1809         if self.token.is_lifetime() {
1810             let lt = self.expect_lifetime();
1811             Ok(self.recover_unclosed_char(lt.ident, err))
1812         } else {
1813             Err(err(self))
1814         }
1815     }
1816
1817     pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
1818         self.parse_opt_token_lit()
1819             .ok_or(())
1820             .or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span)))
1821     }
1822
1823     pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
1824         self.parse_opt_meta_item_lit().ok_or(()).or_else(|()| self.handle_missing_lit())
1825     }
1826
1827     fn recover_after_dot(&mut self) -> Option<Token> {
1828         let mut recovered = None;
1829         if self.token == token::Dot {
1830             // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
1831             // dot would follow an optional literal, so we do this unconditionally.
1832             recovered = self.look_ahead(1, |next_token| {
1833                 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
1834                     next_token.kind
1835                 {
1836                     if self.token.span.hi() == next_token.span.lo() {
1837                         let s = String::from("0.") + symbol.as_str();
1838                         let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
1839                         return Some(Token::new(kind, self.token.span.to(next_token.span)));
1840                     }
1841                 }
1842                 None
1843             });
1844             if let Some(token) = &recovered {
1845                 self.bump();
1846                 self.sess.emit_err(FloatLiteralRequiresIntegerPart {
1847                     span: token.span,
1848                     correct: pprust::token_to_string(token).into_owned(),
1849                 });
1850             }
1851         }
1852
1853         recovered
1854     }
1855
1856     /// Matches `lit = true | false | token_lit`.
1857     /// Returns `None` if the next token is not a literal.
1858     pub(super) fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
1859         let recovered = self.recover_after_dot();
1860         let token = recovered.as_ref().unwrap_or(&self.token);
1861         let span = token.span;
1862         token::Lit::from_token(token).map(|token_lit| {
1863             self.bump();
1864             (token_lit, span)
1865         })
1866     }
1867
1868     /// Matches `lit = true | false | token_lit`.
1869     /// Returns `None` if the next token is not a literal.
1870     pub(super) fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
1871         let recovered = self.recover_after_dot();
1872         let token = recovered.as_ref().unwrap_or(&self.token);
1873         match token::Lit::from_token(token) {
1874             Some(token_lit) => {
1875                 match MetaItemLit::from_token_lit(token_lit, token.span) {
1876                     Ok(lit) => {
1877                         self.bump();
1878                         Some(lit)
1879                     }
1880                     Err(err) => {
1881                         let span = token.span;
1882                         let token::Literal(lit) = token.kind else {
1883                             unreachable!();
1884                         };
1885                         self.bump();
1886                         report_lit_error(&self.sess, err, lit, span);
1887                         // Pack possible quotes and prefixes from the original literal into
1888                         // the error literal's symbol so they can be pretty-printed faithfully.
1889                         let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
1890                         let symbol = Symbol::intern(&suffixless_lit.to_string());
1891                         let lit = token::Lit::new(token::Err, symbol, lit.suffix);
1892                         Some(
1893                             MetaItemLit::from_token_lit(lit, span)
1894                                 .unwrap_or_else(|_| unreachable!()),
1895                         )
1896                     }
1897                 }
1898             }
1899             None => None,
1900         }
1901     }
1902
1903     pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
1904         if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
1905             // #59553: warn instead of reject out of hand to allow the fix to percolate
1906             // through the ecosystem when people fix their macros
1907             self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex {
1908                 span,
1909                 suffix,
1910                 exception: Some(()),
1911             });
1912         } else {
1913             self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None });
1914         }
1915     }
1916
1917     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
1918     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
1919     pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
1920         maybe_whole_expr!(self);
1921
1922         let lo = self.token.span;
1923         let minus_present = self.eat(&token::BinOp(token::Minus));
1924         let (token_lit, span) = self.parse_token_lit()?;
1925         let expr = self.mk_expr(span, ExprKind::Lit(token_lit));
1926
1927         if minus_present {
1928             Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
1929         } else {
1930             Ok(expr)
1931         }
1932     }
1933
1934     fn is_array_like_block(&mut self) -> bool {
1935         self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
1936             && self.look_ahead(2, |t| t == &token::Comma)
1937             && self.look_ahead(3, |t| t.can_begin_expr())
1938     }
1939
1940     /// Emits a suggestion if it looks like the user meant an array but
1941     /// accidentally used braces, causing the code to be interpreted as a block
1942     /// expression.
1943     fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
1944         let mut snapshot = self.create_snapshot_for_diagnostic();
1945         match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
1946             Ok(arr) => {
1947                 self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
1948                     span: arr.span,
1949                     sub: ArrayBracketsInsteadOfSpacesSugg {
1950                         left: lo,
1951                         right: snapshot.prev_token.span,
1952                     },
1953                 });
1954
1955                 self.restore_snapshot(snapshot);
1956                 Some(self.mk_expr_err(arr.span))
1957             }
1958             Err(e) => {
1959                 e.cancel();
1960                 None
1961             }
1962         }
1963     }
1964
1965     fn suggest_missing_semicolon_before_array(
1966         &self,
1967         prev_span: Span,
1968         open_delim_span: Span,
1969     ) -> PResult<'a, ()> {
1970         if !self.may_recover() {
1971             return Ok(());
1972         }
1973
1974         if self.token.kind == token::Comma {
1975             if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) {
1976                 return Ok(());
1977             }
1978             let mut snapshot = self.create_snapshot_for_diagnostic();
1979             snapshot.bump();
1980             match snapshot.parse_seq_to_before_end(
1981                 &token::CloseDelim(Delimiter::Bracket),
1982                 SeqSep::trailing_allowed(token::Comma),
1983                 |p| p.parse_expr(),
1984             ) {
1985                 Ok(_)
1986                     // When the close delim is `)`, `token.kind` is expected to be `token::CloseDelim(Delimiter::Parenthesis)`,
1987                     // but the actual `token.kind` is `token::CloseDelim(Delimiter::Bracket)`.
1988                     // This is because the `token.kind` of the close delim is treated as the same as
1989                     // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
1990                     // Therefore, `token.kind` should not be compared here.
1991                     if snapshot
1992                         .span_to_snippet(snapshot.token.span)
1993                         .map_or(false, |snippet| snippet == "]") =>
1994                 {
1995                     return Err(MissingSemicolonBeforeArray {
1996                         open_delim: open_delim_span,
1997                         semicolon: prev_span.shrink_to_hi(),
1998                     }.into_diagnostic(&self.sess.span_diagnostic));
1999                 }
2000                 Ok(_) => (),
2001                 Err(err) => err.cancel(),
2002             }
2003         }
2004         Ok(())
2005     }
2006
2007     /// Parses a block or unsafe block.
2008     pub(super) fn parse_block_expr(
2009         &mut self,
2010         opt_label: Option<Label>,
2011         lo: Span,
2012         blk_mode: BlockCheckMode,
2013     ) -> PResult<'a, P<Expr>> {
2014         if self.may_recover() && self.is_array_like_block() {
2015             if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
2016                 return Ok(arr);
2017             }
2018         }
2019
2020         if self.token.is_whole_block() {
2021             self.sess.emit_err(InvalidBlockMacroSegment {
2022                 span: self.token.span,
2023                 context: lo.to(self.token.span),
2024             });
2025         }
2026
2027         let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
2028         Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
2029     }
2030
2031     /// Parse a block which takes no attributes and has no label
2032     fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
2033         let blk = self.parse_block()?;
2034         Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
2035     }
2036
2037     /// Parses a closure expression (e.g., `move |args| expr`).
2038     fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
2039         let lo = self.token.span;
2040
2041         let binder = if self.check_keyword(kw::For) {
2042             let lo = self.token.span;
2043             let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
2044             let span = lo.to(self.prev_token.span);
2045
2046             self.sess.gated_spans.gate(sym::closure_lifetime_binder, span);
2047
2048             ClosureBinder::For { span, generic_params: P::from_vec(lifetime_defs) }
2049         } else {
2050             ClosureBinder::NotPresent
2051         };
2052
2053         let movability =
2054             if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
2055
2056         let asyncness = if self.token.uninterpolated_span().rust_2018() {
2057             self.parse_asyncness(Case::Sensitive)
2058         } else {
2059             Async::No
2060         };
2061
2062         let capture_clause = self.parse_capture_clause()?;
2063         let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
2064         let decl_hi = self.prev_token.span;
2065         let mut body = match fn_decl.output {
2066             FnRetTy::Default(_) => {
2067                 let restrictions = self.restrictions - Restrictions::STMT_EXPR;
2068                 self.parse_expr_res(restrictions, None)?
2069             }
2070             _ => {
2071                 // If an explicit return type is given, require a block to appear (RFC 968).
2072                 let body_lo = self.token.span;
2073                 self.parse_block_expr(None, body_lo, BlockCheckMode::Default)?
2074             }
2075         };
2076
2077         if let Async::Yes { span, .. } = asyncness {
2078             // Feature-gate `async ||` closures.
2079             self.sess.gated_spans.gate(sym::async_closure, span);
2080         }
2081
2082         if self.token.kind == TokenKind::Semi
2083             && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
2084             && self.may_recover()
2085         {
2086             // It is likely that the closure body is a block but where the
2087             // braces have been removed. We will recover and eat the next
2088             // statements later in the parsing process.
2089             body = self.mk_expr_err(body.span);
2090         }
2091
2092         let body_span = body.span;
2093
2094         let closure = self.mk_expr(
2095             lo.to(body.span),
2096             ExprKind::Closure(Box::new(ast::Closure {
2097                 binder,
2098                 capture_clause,
2099                 asyncness,
2100                 movability,
2101                 fn_decl,
2102                 body,
2103                 fn_decl_span: lo.to(decl_hi),
2104                 fn_arg_span,
2105             })),
2106         );
2107
2108         // Disable recovery for closure body
2109         let spans =
2110             ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
2111         self.current_closure = Some(spans);
2112
2113         Ok(closure)
2114     }
2115
2116     /// Parses an optional `move` prefix to a closure-like construct.
2117     fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
2118         if self.eat_keyword(kw::Move) {
2119             // Check for `move async` and recover
2120             if self.check_keyword(kw::Async) {
2121                 let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2122                 Err(AsyncMoveOrderIncorrect { span: move_async_span }
2123                     .into_diagnostic(&self.sess.span_diagnostic))
2124             } else {
2125                 Ok(CaptureBy::Value)
2126             }
2127         } else {
2128             Ok(CaptureBy::Ref)
2129         }
2130     }
2131
2132     /// Parses the `|arg, arg|` header of a closure.
2133     fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> {
2134         let arg_start = self.token.span.lo();
2135
2136         let inputs = if self.eat(&token::OrOr) {
2137             Vec::new()
2138         } else {
2139             self.expect(&token::BinOp(token::Or))?;
2140             let args = self
2141                 .parse_seq_to_before_tokens(
2142                     &[&token::BinOp(token::Or), &token::OrOr],
2143                     SeqSep::trailing_allowed(token::Comma),
2144                     TokenExpectType::NoExpect,
2145                     |p| p.parse_fn_block_param(),
2146                 )?
2147                 .0;
2148             self.expect_or()?;
2149             args
2150         };
2151         let arg_span = self.prev_token.span.with_lo(arg_start);
2152         let output =
2153             self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?;
2154
2155         Ok((P(FnDecl { inputs, output }), arg_span))
2156     }
2157
2158     /// Parses a parameter in a closure header (e.g., `|arg, arg|`).
2159     fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
2160         let lo = self.token.span;
2161         let attrs = self.parse_outer_attributes()?;
2162         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
2163             let pat = this.parse_pat_no_top_alt(PARAM_EXPECTED)?;
2164             let ty = if this.eat(&token::Colon) {
2165                 this.parse_ty()?
2166             } else {
2167                 this.mk_ty(this.prev_token.span, TyKind::Infer)
2168             };
2169
2170             Ok((
2171                 Param {
2172                     attrs,
2173                     ty,
2174                     pat,
2175                     span: lo.to(this.prev_token.span),
2176                     id: DUMMY_NODE_ID,
2177                     is_placeholder: false,
2178                 },
2179                 TrailingToken::MaybeComma,
2180             ))
2181         })
2182     }
2183
2184     /// Parses an `if` expression (`if` token already eaten).
2185     fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
2186         let lo = self.prev_token.span;
2187         let cond = self.parse_cond_expr()?;
2188         self.parse_if_after_cond(lo, cond)
2189     }
2190
2191     fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> {
2192         let cond_span = cond.span;
2193         // Tries to interpret `cond` as either a missing expression if it's a block,
2194         // or as an unfinished expression if it's a binop and the RHS is a block.
2195         // We could probably add more recoveries here too...
2196         let mut recover_block_from_condition = |this: &mut Self| {
2197             let block = match &mut cond.kind {
2198                 ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
2199                     if let ExprKind::Block(_, None) = right.kind => {
2200                         self.sess.emit_err(IfExpressionMissingThenBlock {
2201                             if_span: lo,
2202                             sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(
2203                                 cond_span.shrink_to_lo().to(*binop_span)
2204                             ),
2205                         });
2206                         std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
2207                     },
2208                 ExprKind::Block(_, None) => {
2209                     self.sess.emit_err(IfExpressionMissingCondition {
2210                         if_span: lo.shrink_to_hi(),
2211                         block_span: self.sess.source_map().start_point(cond_span),
2212                     });
2213                     std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
2214                 }
2215                 _ => {
2216                     return None;
2217                 }
2218             };
2219             if let ExprKind::Block(block, _) = &block.kind {
2220                 Some(block.clone())
2221             } else {
2222                 unreachable!()
2223             }
2224         };
2225         // Parse then block
2226         let thn = if self.token.is_keyword(kw::Else) {
2227             if let Some(block) = recover_block_from_condition(self) {
2228                 block
2229             } else {
2230                 self.sess.emit_err(IfExpressionMissingThenBlock {
2231                     if_span: lo,
2232                     sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()),
2233                 });
2234                 self.mk_block_err(cond_span.shrink_to_hi())
2235             }
2236         } else {
2237             let attrs = self.parse_outer_attributes()?; // For recovery.
2238             let block = if self.check(&token::OpenDelim(Delimiter::Brace)) {
2239                 self.parse_block()?
2240             } else {
2241                 if let Some(block) = recover_block_from_condition(self) {
2242                     block
2243                 } else {
2244                     self.error_on_extra_if(&cond)?;
2245                     // Parse block, which will always fail, but we can add a nice note to the error
2246                     self.parse_block().map_err(|mut err| {
2247                         err.span_note(
2248                             cond_span,
2249                             "the `if` expression is missing a block after this condition",
2250                         );
2251                         err
2252                     })?
2253                 }
2254             };
2255             self.error_on_if_block_attrs(lo, false, block.span, attrs);
2256             block
2257         };
2258         let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
2259         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
2260     }
2261
2262     /// Parses the condition of a `if` or `while` expression.
2263     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
2264         let cond =
2265             self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
2266
2267         if let ExprKind::Let(..) = cond.kind {
2268             // Remove the last feature gating of a `let` expression since it's stable.
2269             self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
2270         }
2271
2272         Ok(cond)
2273     }
2274
2275     /// Parses a `let $pat = $expr` pseudo-expression.
2276     fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
2277         // This is a *approximate* heuristic that detects if `let` chains are
2278         // being parsed in the right position. It's approximate because it
2279         // doesn't deny all invalid `let` expressions, just completely wrong usages.
2280         let not_in_chain = !matches!(
2281             self.prev_token.kind,
2282             TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
2283         );
2284         if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
2285             self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
2286         }
2287
2288         self.bump(); // Eat `let` token
2289         let lo = self.prev_token.span;
2290         let pat = self.parse_pat_allow_top_alt(
2291             None,
2292             RecoverComma::Yes,
2293             RecoverColon::Yes,
2294             CommaRecoveryMode::LikelyTuple,
2295         )?;
2296         if self.token == token::EqEq {
2297             self.sess.emit_err(ExpectedEqForLetExpr {
2298                 span: self.token.span,
2299                 sugg_span: self.token.span,
2300             });
2301             self.bump();
2302         } else {
2303             self.expect(&token::Eq)?;
2304         }
2305         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
2306             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
2307         })?;
2308         let span = lo.to(expr.span);
2309         self.sess.gated_spans.gate(sym::let_chains, span);
2310         Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span)))
2311     }
2312
2313     /// Parses an `else { ... }` expression (`else` token already eaten).
2314     fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
2315         let else_span = self.prev_token.span; // `else`
2316         let attrs = self.parse_outer_attributes()?; // For recovery.
2317         let expr = if self.eat_keyword(kw::If) {
2318             self.parse_if_expr()?
2319         } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
2320             self.parse_simple_block()?
2321         } else {
2322             let snapshot = self.create_snapshot_for_diagnostic();
2323             let first_tok = super::token_descr(&self.token);
2324             let first_tok_span = self.token.span;
2325             match self.parse_expr() {
2326                 Ok(cond)
2327                 // If it's not a free-standing expression, and is followed by a block,
2328                 // then it's very likely the condition to an `else if`.
2329                     if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
2330                         && classify::expr_requires_semi_to_be_stmt(&cond) =>
2331                 {
2332                     self.sess.emit_err(ExpectedElseBlock {
2333                         first_tok_span,
2334                         first_tok,
2335                         else_span,
2336                         condition_start: cond.span.shrink_to_lo(),
2337                     });
2338                     self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
2339                 }
2340                 Err(e) => {
2341                     e.cancel();
2342                     self.restore_snapshot(snapshot);
2343                     self.parse_simple_block()?
2344                 },
2345                 Ok(_) => {
2346                     self.restore_snapshot(snapshot);
2347                     self.parse_simple_block()?
2348                 },
2349             }
2350         };
2351         self.error_on_if_block_attrs(else_span, true, expr.span, attrs);
2352         Ok(expr)
2353     }
2354
2355     fn error_on_if_block_attrs(
2356         &self,
2357         ctx_span: Span,
2358         is_ctx_else: bool,
2359         branch_span: Span,
2360         attrs: AttrWrapper,
2361     ) {
2362         if attrs.is_empty() {
2363             return;
2364         }
2365
2366         let attrs: &[ast::Attribute] = &attrs.take_for_recovery(self.sess);
2367         let (attributes, last) = match attrs {
2368             [] => return,
2369             [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
2370         };
2371         let ctx = if is_ctx_else { "else" } else { "if" };
2372         self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
2373             last,
2374             branch_span,
2375             ctx_span,
2376             ctx: ctx.to_string(),
2377             attributes,
2378         });
2379     }
2380
2381     fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> {
2382         if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind &&
2383             let BinOpKind::And = binop &&
2384             let ExprKind::If(cond, ..) = &right.kind {
2385                     Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
2386             } else {
2387                 Ok(())
2388             }
2389     }
2390
2391     /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
2392     fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2393         // Record whether we are about to parse `for (`.
2394         // This is used below for recovery in case of `for ( $stuff ) $block`
2395         // in which case we will suggest `for $stuff $block`.
2396         let begin_paren = match self.token.kind {
2397             token::OpenDelim(Delimiter::Parenthesis) => Some(self.token.span),
2398             _ => None,
2399         };
2400
2401         let pat = self.parse_pat_allow_top_alt(
2402             None,
2403             RecoverComma::Yes,
2404             RecoverColon::Yes,
2405             CommaRecoveryMode::LikelyTuple,
2406         )?;
2407         if !self.eat_keyword(kw::In) {
2408             self.error_missing_in_for_loop();
2409         }
2410         self.check_for_for_in_in_typo(self.prev_token.span);
2411         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
2412
2413         let pat = self.recover_parens_around_for_head(pat, begin_paren);
2414
2415         let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
2416
2417         let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
2418         Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
2419     }
2420
2421     fn error_missing_in_for_loop(&mut self) {
2422         let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
2423             // Possibly using JS syntax (#75311).
2424             let span = self.token.span;
2425             self.bump();
2426             (span, MissingInInForLoopSub::InNotOf)
2427         } else {
2428             (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
2429         };
2430
2431         self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
2432     }
2433
2434     /// Parses a `while` or `while let` expression (`while` token already eaten).
2435     fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2436         let cond = self.parse_cond_expr().map_err(|mut err| {
2437             err.span_label(lo, "while parsing the condition of this `while` expression");
2438             err
2439         })?;
2440         let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| {
2441             err.span_label(lo, "while parsing the body of this `while` expression");
2442             err.span_label(cond.span, "this `while` condition successfully parsed");
2443             err
2444         })?;
2445         Ok(self.mk_expr_with_attrs(
2446             lo.to(self.prev_token.span),
2447             ExprKind::While(cond, body, opt_label),
2448             attrs,
2449         ))
2450     }
2451
2452     /// Parses `loop { ... }` (`loop` token already eaten).
2453     fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2454         let loop_span = self.prev_token.span;
2455         let (attrs, body) = self.parse_inner_attrs_and_block()?;
2456         Ok(self.mk_expr_with_attrs(
2457             lo.to(self.prev_token.span),
2458             ExprKind::Loop(body, opt_label, loop_span),
2459             attrs,
2460         ))
2461     }
2462
2463     pub(crate) fn eat_label(&mut self) -> Option<Label> {
2464         self.token.lifetime().map(|ident| {
2465             self.bump();
2466             Label { ident }
2467         })
2468     }
2469
2470     /// Parses a `match ... { ... }` expression (`match` token already eaten).
2471     fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
2472         let match_span = self.prev_token.span;
2473         let lo = self.prev_token.span;
2474         let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
2475         if let Err(mut e) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
2476             if self.token == token::Semi {
2477                 e.span_suggestion_short(
2478                     match_span,
2479                     "try removing this `match`",
2480                     "",
2481                     Applicability::MaybeIncorrect, // speculative
2482                 );
2483             }
2484             if self.maybe_recover_unexpected_block_label() {
2485                 e.cancel();
2486                 self.bump();
2487             } else {
2488                 return Err(e);
2489             }
2490         }
2491         let attrs = self.parse_inner_attributes()?;
2492
2493         let mut arms: Vec<Arm> = Vec::new();
2494         while self.token != token::CloseDelim(Delimiter::Brace) {
2495             match self.parse_arm() {
2496                 Ok(arm) => arms.push(arm),
2497                 Err(mut e) => {
2498                     // Recover by skipping to the end of the block.
2499                     e.emit();
2500                     self.recover_stmt();
2501                     let span = lo.to(self.token.span);
2502                     if self.token == token::CloseDelim(Delimiter::Brace) {
2503                         self.bump();
2504                     }
2505                     return Ok(self.mk_expr_with_attrs(
2506                         span,
2507                         ExprKind::Match(scrutinee, arms),
2508                         attrs,
2509                     ));
2510                 }
2511             }
2512         }
2513         let hi = self.token.span;
2514         self.bump();
2515         Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs))
2516     }
2517
2518     /// Attempt to recover from match arm body with statements and no surrounding braces.
2519     fn parse_arm_body_missing_braces(
2520         &mut self,
2521         first_expr: &P<Expr>,
2522         arrow_span: Span,
2523     ) -> Option<P<Expr>> {
2524         if self.token.kind != token::Semi {
2525             return None;
2526         }
2527         let start_snapshot = self.create_snapshot_for_diagnostic();
2528         let semi_sp = self.token.span;
2529         self.bump(); // `;`
2530         let mut stmts =
2531             vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
2532         let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
2533             let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
2534
2535             this.sess.emit_err(MatchArmBodyWithoutBraces {
2536                 statements: span,
2537                 arrow: arrow_span,
2538                 num_statements: stmts.len(),
2539                 sub: if stmts.len() > 1 {
2540                     MatchArmBodyWithoutBracesSugg::AddBraces {
2541                         left: span.shrink_to_lo(),
2542                         right: span.shrink_to_hi(),
2543                     }
2544                 } else {
2545                     MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
2546                 },
2547             });
2548             this.mk_expr_err(span)
2549         };
2550         // We might have either a `,` -> `;` typo, or a block without braces. We need
2551         // a more subtle parsing strategy.
2552         loop {
2553             if self.token.kind == token::CloseDelim(Delimiter::Brace) {
2554                 // We have reached the closing brace of the `match` expression.
2555                 return Some(err(self, stmts));
2556             }
2557             if self.token.kind == token::Comma {
2558                 self.restore_snapshot(start_snapshot);
2559                 return None;
2560             }
2561             let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
2562             match self.parse_pat_no_top_alt(None) {
2563                 Ok(_pat) => {
2564                     if self.token.kind == token::FatArrow {
2565                         // Reached arm end.
2566                         self.restore_snapshot(pre_pat_snapshot);
2567                         return Some(err(self, stmts));
2568                     }
2569                 }
2570                 Err(err) => {
2571                     err.cancel();
2572                 }
2573             }
2574
2575             self.restore_snapshot(pre_pat_snapshot);
2576             match self.parse_stmt_without_recovery(true, ForceCollect::No) {
2577                 // Consume statements for as long as possible.
2578                 Ok(Some(stmt)) => {
2579                     stmts.push(stmt);
2580                 }
2581                 Ok(None) => {
2582                     self.restore_snapshot(start_snapshot);
2583                     break;
2584                 }
2585                 // We couldn't parse either yet another statement missing it's
2586                 // enclosing block nor the next arm's pattern or closing brace.
2587                 Err(stmt_err) => {
2588                     stmt_err.cancel();
2589                     self.restore_snapshot(start_snapshot);
2590                     break;
2591                 }
2592             }
2593         }
2594         None
2595     }
2596
2597     pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
2598         // Used to check the `let_chains` and `if_let_guard` features mostly by scanning
2599         // `&&` tokens.
2600         fn check_let_expr(expr: &Expr) -> (bool, bool) {
2601             match &expr.kind {
2602                 ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
2603                     let lhs_rslt = check_let_expr(lhs);
2604                     let rhs_rslt = check_let_expr(rhs);
2605                     (lhs_rslt.0 || rhs_rslt.0, false)
2606                 }
2607                 ExprKind::Let(..) => (true, true),
2608                 _ => (false, true),
2609             }
2610         }
2611         let attrs = self.parse_outer_attributes()?;
2612         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
2613             let lo = this.token.span;
2614             let pat = this.parse_pat_allow_top_alt(
2615                 None,
2616                 RecoverComma::Yes,
2617                 RecoverColon::Yes,
2618                 CommaRecoveryMode::EitherTupleOrPipe,
2619             )?;
2620             let guard = if this.eat_keyword(kw::If) {
2621                 let if_span = this.prev_token.span;
2622                 let cond = this.parse_expr_res(Restrictions::ALLOW_LET, None)?;
2623                 let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
2624                 if has_let_expr {
2625                     if does_not_have_bin_op {
2626                         // Remove the last feature gating of a `let` expression since it's stable.
2627                         this.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
2628                     }
2629                     let span = if_span.to(cond.span);
2630                     this.sess.gated_spans.gate(sym::if_let_guard, span);
2631                 }
2632                 Some(cond)
2633             } else {
2634                 None
2635             };
2636             let arrow_span = this.token.span;
2637             if let Err(mut err) = this.expect(&token::FatArrow) {
2638                 // We might have a `=>` -> `=` or `->` typo (issue #89396).
2639                 if TokenKind::FatArrow
2640                     .similar_tokens()
2641                     .map_or(false, |similar_tokens| similar_tokens.contains(&this.token.kind))
2642                 {
2643                     err.span_suggestion(
2644                         this.token.span,
2645                         "try using a fat arrow here",
2646                         "=>",
2647                         Applicability::MaybeIncorrect,
2648                     );
2649                     err.emit();
2650                     this.bump();
2651                 } else {
2652                     return Err(err);
2653                 }
2654             }
2655             let arm_start_span = this.token.span;
2656
2657             let expr = this.parse_expr_res(Restrictions::STMT_EXPR, None).map_err(|mut err| {
2658                 err.span_label(arrow_span, "while parsing the `match` arm starting here");
2659                 err
2660             })?;
2661
2662             let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
2663                 && this.token != token::CloseDelim(Delimiter::Brace);
2664
2665             let hi = this.prev_token.span;
2666
2667             if require_comma {
2668                 let sm = this.sess.source_map();
2669                 if let Some(body) = this.parse_arm_body_missing_braces(&expr, arrow_span) {
2670                     let span = body.span;
2671                     return Ok((
2672                         ast::Arm {
2673                             attrs,
2674                             pat,
2675                             guard,
2676                             body,
2677                             span,
2678                             id: DUMMY_NODE_ID,
2679                             is_placeholder: false,
2680                         },
2681                         TrailingToken::None,
2682                     ));
2683                 }
2684                 this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
2685                     .or_else(|mut err| {
2686                         if this.token == token::FatArrow {
2687                             if let Ok(expr_lines) = sm.span_to_lines(expr.span)
2688                             && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
2689                             && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
2690                             && expr_lines.lines.len() == 2
2691                             {
2692                                 // We check whether there's any trailing code in the parse span,
2693                                 // if there isn't, we very likely have the following:
2694                                 //
2695                                 // X |     &Y => "y"
2696                                 //   |        --    - missing comma
2697                                 //   |        |
2698                                 //   |        arrow_span
2699                                 // X |     &X => "x"
2700                                 //   |      - ^^ self.token.span
2701                                 //   |      |
2702                                 //   |      parsed until here as `"y" & X`
2703                                 err.span_suggestion_short(
2704                                     arm_start_span.shrink_to_hi(),
2705                                     "missing a comma here to end this `match` arm",
2706                                     ",",
2707                                     Applicability::MachineApplicable,
2708                                 );
2709                                 return Err(err);
2710                             }
2711                         } else {
2712                             // FIXME(compiler-errors): We could also recover `; PAT =>` here
2713
2714                             // Try to parse a following `PAT =>`, if successful
2715                             // then we should recover.
2716                             let mut snapshot = this.create_snapshot_for_diagnostic();
2717                             let pattern_follows = snapshot
2718                                 .parse_pat_allow_top_alt(
2719                                     None,
2720                                     RecoverComma::Yes,
2721                                     RecoverColon::Yes,
2722                                     CommaRecoveryMode::EitherTupleOrPipe,
2723                                 )
2724                                 .map_err(|err| err.cancel())
2725                                 .is_ok();
2726                             if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
2727                                 err.cancel();
2728                                 this.sess.emit_err(MissingCommaAfterMatchArm {
2729                                     span: hi.shrink_to_hi(),
2730                                 });
2731                                 return Ok(true);
2732                             }
2733                         }
2734                         err.span_label(arrow_span, "while parsing the `match` arm starting here");
2735                         Err(err)
2736                     })?;
2737             } else {
2738                 this.eat(&token::Comma);
2739             }
2740
2741             Ok((
2742                 ast::Arm {
2743                     attrs,
2744                     pat,
2745                     guard,
2746                     body: expr,
2747                     span: lo.to(hi),
2748                     id: DUMMY_NODE_ID,
2749                     is_placeholder: false,
2750                 },
2751                 TrailingToken::None,
2752             ))
2753         })
2754     }
2755
2756     /// Parses a `try {...}` expression (`try` token already eaten).
2757     fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
2758         let (attrs, body) = self.parse_inner_attrs_and_block()?;
2759         if self.eat_keyword(kw::Catch) {
2760             Err(CatchAfterTry { span: self.prev_token.span }
2761                 .into_diagnostic(&self.sess.span_diagnostic))
2762         } else {
2763             let span = span_lo.to(body.span);
2764             self.sess.gated_spans.gate(sym::try_blocks, span);
2765             Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs))
2766         }
2767     }
2768
2769     fn is_do_catch_block(&self) -> bool {
2770         self.token.is_keyword(kw::Do)
2771             && self.is_keyword_ahead(1, &[kw::Catch])
2772             && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace))
2773             && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
2774     }
2775
2776     fn is_do_yeet(&self) -> bool {
2777         self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet])
2778     }
2779
2780     fn is_try_block(&self) -> bool {
2781         self.token.is_keyword(kw::Try)
2782             && self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
2783             && self.token.uninterpolated_span().rust_2018()
2784     }
2785
2786     /// Parses an `async move? {...}` expression.
2787     fn parse_async_block(&mut self) -> PResult<'a, P<Expr>> {
2788         let lo = self.token.span;
2789         self.expect_keyword(kw::Async)?;
2790         let capture_clause = self.parse_capture_clause()?;
2791         let (attrs, body) = self.parse_inner_attrs_and_block()?;
2792         let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body);
2793         Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
2794     }
2795
2796     fn is_async_block(&self) -> bool {
2797         self.token.is_keyword(kw::Async)
2798             && ((
2799                 // `async move {`
2800                 self.is_keyword_ahead(1, &[kw::Move])
2801                     && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace))
2802             ) || (
2803                 // `async {`
2804                 self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
2805             ))
2806     }
2807
2808     fn is_certainly_not_a_block(&self) -> bool {
2809         self.look_ahead(1, |t| t.is_ident())
2810             && (
2811                 // `{ ident, ` cannot start a block.
2812                 self.look_ahead(2, |t| t == &token::Comma)
2813                     || self.look_ahead(2, |t| t == &token::Colon)
2814                         && (
2815                             // `{ ident: token, ` cannot start a block.
2816                             self.look_ahead(4, |t| t == &token::Comma) ||
2817                 // `{ ident: ` cannot start a block unless it's a type ascription `ident: Type`.
2818                 self.look_ahead(3, |t| !t.can_begin_type())
2819                         )
2820             )
2821     }
2822
2823     fn maybe_parse_struct_expr(
2824         &mut self,
2825         qself: &Option<P<ast::QSelf>>,
2826         path: &ast::Path,
2827     ) -> Option<PResult<'a, P<Expr>>> {
2828         let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
2829         if struct_allowed || self.is_certainly_not_a_block() {
2830             if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
2831                 return Some(Err(err));
2832             }
2833             let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
2834             if let (Ok(expr), false) = (&expr, struct_allowed) {
2835                 // This is a struct literal, but we don't can't accept them here.
2836                 self.sess.emit_err(StructLiteralNotAllowedHere {
2837                     span: expr.span,
2838                     sub: StructLiteralNotAllowedHereSugg {
2839                         left: path.span.shrink_to_lo(),
2840                         right: expr.span.shrink_to_hi(),
2841                     },
2842                 });
2843             }
2844             return Some(expr);
2845         }
2846         None
2847     }
2848
2849     pub(super) fn parse_struct_fields(
2850         &mut self,
2851         pth: ast::Path,
2852         recover: bool,
2853         close_delim: Delimiter,
2854     ) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
2855         let mut fields = Vec::new();
2856         let mut base = ast::StructRest::None;
2857         let mut recover_async = false;
2858
2859         let mut async_block_err = |e: &mut Diagnostic, span: Span| {
2860             recover_async = true;
2861             e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
2862             e.help_use_latest_edition();
2863         };
2864
2865         while self.token != token::CloseDelim(close_delim) {
2866             if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) {
2867                 let exp_span = self.prev_token.span;
2868                 // We permit `.. }` on the left-hand side of a destructuring assignment.
2869                 if self.check(&token::CloseDelim(close_delim)) {
2870                     base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi());
2871                     break;
2872                 }
2873                 match self.parse_expr() {
2874                     Ok(e) => base = ast::StructRest::Base(e),
2875                     Err(mut e) if recover => {
2876                         e.emit();
2877                         self.recover_stmt();
2878                     }
2879                     Err(e) => return Err(e),
2880                 }
2881                 self.recover_struct_comma_after_dotdot(exp_span);
2882                 break;
2883             }
2884
2885             let recovery_field = self.find_struct_error_after_field_looking_code();
2886             let parsed_field = match self.parse_expr_field() {
2887                 Ok(f) => Some(f),
2888                 Err(mut e) => {
2889                     if pth == kw::Async {
2890                         async_block_err(&mut e, pth.span);
2891                     } else {
2892                         e.span_label(pth.span, "while parsing this struct");
2893                     }
2894                     e.emit();
2895
2896                     // If the next token is a comma, then try to parse
2897                     // what comes next as additional fields, rather than
2898                     // bailing out until next `}`.
2899                     if self.token != token::Comma {
2900                         self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
2901                         if self.token != token::Comma {
2902                             break;
2903                         }
2904                     }
2905                     None
2906                 }
2907             };
2908
2909             let is_shorthand = parsed_field.as_ref().map_or(false, |f| f.is_shorthand);
2910             // A shorthand field can be turned into a full field with `:`.
2911             // We should point this out.
2912             self.check_or_expected(!is_shorthand, TokenType::Token(token::Colon));
2913
2914             match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
2915                 Ok(_) => {
2916                     if let Some(f) = parsed_field.or(recovery_field) {
2917                         // Only include the field if there's no parse error for the field name.
2918                         fields.push(f);
2919                     }
2920                 }
2921                 Err(mut e) => {
2922                     if pth == kw::Async {
2923                         async_block_err(&mut e, pth.span);
2924                     } else {
2925                         e.span_label(pth.span, "while parsing this struct");
2926                         if let Some(f) = recovery_field {
2927                             fields.push(f);
2928                             e.span_suggestion(
2929                                 self.prev_token.span.shrink_to_hi(),
2930                                 "try adding a comma",
2931                                 ",",
2932                                 Applicability::MachineApplicable,
2933                             );
2934                         } else if is_shorthand
2935                             && (AssocOp::from_token(&self.token).is_some()
2936                                 || matches!(&self.token.kind, token::OpenDelim(_))
2937                                 || self.token.kind == token::Dot)
2938                         {
2939                             // Looks like they tried to write a shorthand, complex expression.
2940                             let ident = parsed_field.expect("is_shorthand implies Some").ident;
2941                             e.span_suggestion(
2942                                 ident.span.shrink_to_lo(),
2943                                 "try naming a field",
2944                                 &format!("{ident}: "),
2945                                 Applicability::HasPlaceholders,
2946                             );
2947                         }
2948                     }
2949                     if !recover {
2950                         return Err(e);
2951                     }
2952                     e.emit();
2953                     self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
2954                     self.eat(&token::Comma);
2955                 }
2956             }
2957         }
2958         Ok((fields, base, recover_async))
2959     }
2960
2961     /// Precondition: already parsed the '{'.
2962     pub(super) fn parse_struct_expr(
2963         &mut self,
2964         qself: Option<P<ast::QSelf>>,
2965         pth: ast::Path,
2966         recover: bool,
2967     ) -> PResult<'a, P<Expr>> {
2968         let lo = pth.span;
2969         let (fields, base, recover_async) =
2970             self.parse_struct_fields(pth.clone(), recover, Delimiter::Brace)?;
2971         let span = lo.to(self.token.span);
2972         self.expect(&token::CloseDelim(Delimiter::Brace))?;
2973         let expr = if recover_async {
2974             ExprKind::Err
2975         } else {
2976             ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
2977         };
2978         Ok(self.mk_expr(span, expr))
2979     }
2980
2981     /// Use in case of error after field-looking code: `S { foo: () with a }`.
2982     fn find_struct_error_after_field_looking_code(&self) -> Option<ExprField> {
2983         match self.token.ident() {
2984             Some((ident, is_raw))
2985                 if (is_raw || !ident.is_reserved())
2986                     && self.look_ahead(1, |t| *t == token::Colon) =>
2987             {
2988                 Some(ast::ExprField {
2989                     ident,
2990                     span: self.token.span,
2991                     expr: self.mk_expr_err(self.token.span),
2992                     is_shorthand: false,
2993                     attrs: AttrVec::new(),
2994                     id: DUMMY_NODE_ID,
2995                     is_placeholder: false,
2996                 })
2997             }
2998             _ => None,
2999         }
3000     }
3001
3002     fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
3003         if self.token != token::Comma {
3004             return;
3005         }
3006         self.sess.emit_err(CommaAfterBaseStruct {
3007             span: span.to(self.prev_token.span),
3008             comma: self.token.span,
3009         });
3010         self.recover_stmt();
3011     }
3012
3013     fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool {
3014         if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim))
3015             && self.eat(&token::DotDotDot)
3016         {
3017             // recover from typo of `...`, suggest `..`
3018             let span = self.prev_token.span;
3019             self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
3020             return true;
3021         }
3022         false
3023     }
3024
3025     /// Parses `ident (COLON expr)?`.
3026     fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
3027         let attrs = self.parse_outer_attributes()?;
3028         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
3029             let lo = this.token.span;
3030
3031             // Check if a colon exists one ahead. This means we're parsing a fieldname.
3032             let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
3033             let (ident, expr) = if is_shorthand {
3034                 // Mimic `x: x` for the `x` field shorthand.
3035                 let ident = this.parse_ident_common(false)?;
3036                 let path = ast::Path::from_ident(ident);
3037                 (ident, this.mk_expr(ident.span, ExprKind::Path(None, path)))
3038             } else {
3039                 let ident = this.parse_field_name()?;
3040                 this.error_on_eq_field_init(ident);
3041                 this.bump(); // `:`
3042                 (ident, this.parse_expr()?)
3043             };
3044
3045             Ok((
3046                 ast::ExprField {
3047                     ident,
3048                     span: lo.to(expr.span),
3049                     expr,
3050                     is_shorthand,
3051                     attrs,
3052                     id: DUMMY_NODE_ID,
3053                     is_placeholder: false,
3054                 },
3055                 TrailingToken::MaybeComma,
3056             ))
3057         })
3058     }
3059
3060     /// Check for `=`. This means the source incorrectly attempts to
3061     /// initialize a field with an eq rather than a colon.
3062     fn error_on_eq_field_init(&self, field_name: Ident) {
3063         if self.token != token::Eq {
3064             return;
3065         }
3066
3067         self.sess.emit_err(EqFieldInit {
3068             span: self.token.span,
3069             eq: field_name.span.shrink_to_hi().to(self.token.span),
3070         });
3071     }
3072
3073     fn err_dotdotdot_syntax(&self, span: Span) {
3074         self.sess.emit_err(DotDotDot { span });
3075     }
3076
3077     fn err_larrow_operator(&self, span: Span) {
3078         self.sess.emit_err(LeftArrowOperator { span });
3079     }
3080
3081     fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
3082         ExprKind::AssignOp(binop, lhs, rhs)
3083     }
3084
3085     fn mk_range(
3086         &mut self,
3087         start: Option<P<Expr>>,
3088         end: Option<P<Expr>>,
3089         limits: RangeLimits,
3090     ) -> ExprKind {
3091         if end.is_none() && limits == RangeLimits::Closed {
3092             self.inclusive_range_with_incorrect_end(self.prev_token.span);
3093             ExprKind::Err
3094         } else {
3095             ExprKind::Range(start, end, limits)
3096         }
3097     }
3098
3099     fn mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind {
3100         ExprKind::Unary(unop, expr)
3101     }
3102
3103     fn mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
3104         ExprKind::Binary(binop, lhs, rhs)
3105     }
3106
3107     fn mk_index(&self, expr: P<Expr>, idx: P<Expr>) -> ExprKind {
3108         ExprKind::Index(expr, idx)
3109     }
3110
3111     fn mk_call(&self, f: P<Expr>, args: Vec<P<Expr>>) -> ExprKind {
3112         ExprKind::Call(f, args)
3113     }
3114
3115     fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
3116         let span = lo.to(self.prev_token.span);
3117         let await_expr = self.mk_expr(span, ExprKind::Await(self_arg));
3118         self.recover_from_await_method_call();
3119         await_expr
3120     }
3121
3122     pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
3123         P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
3124     }
3125
3126     pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
3127         P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None })
3128     }
3129
3130     pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
3131         self.mk_expr(span, ExprKind::Err)
3132     }
3133
3134     /// Create expression span ensuring the span of the parent node
3135     /// is larger than the span of lhs and rhs, including the attributes.
3136     fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
3137         lhs.attrs
3138             .iter()
3139             .find(|a| a.style == AttrStyle::Outer)
3140             .map_or(lhs_span, |a| a.span)
3141             .to(rhs_span)
3142     }
3143
3144     fn collect_tokens_for_expr(
3145         &mut self,
3146         attrs: AttrWrapper,
3147         f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>,
3148     ) -> PResult<'a, P<Expr>> {
3149         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
3150             let res = f(this, attrs)?;
3151             let trailing = if this.restrictions.contains(Restrictions::STMT_EXPR)
3152                 && this.token.kind == token::Semi
3153             {
3154                 TrailingToken::Semi
3155             } else if this.token.kind == token::Gt {
3156                 TrailingToken::Gt
3157             } else {
3158                 // FIXME - pass this through from the place where we know
3159                 // we need a comma, rather than assuming that `#[attr] expr,`
3160                 // always captures a trailing comma
3161                 TrailingToken::MaybeComma
3162             };
3163             Ok((res, trailing))
3164         })
3165     }
3166 }