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