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