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