rustc_parse/parser/
expr.rs

1// ignore-tidy-filelength
2
3use core::mem;
4use core::ops::{Bound, ControlFlow};
5
6use ast::mut_visit::{self, MutVisitor};
7use ast::token::IdentIsRaw;
8use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
9use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind};
10use rustc_ast::tokenstream::TokenTree;
11use rustc_ast::util::case::Case;
12use rustc_ast::util::classify;
13use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par};
14use rustc_ast::visit::{Visitor, walk_expr};
15use rustc_ast::{
16    self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind,
17    BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl,
18    FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits,
19    StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
20};
21use rustc_data_structures::stack::ensure_sufficient_stack;
22use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
23use rustc_literal_escaper::unescape_char;
24use rustc_macros::Subdiagnostic;
25use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
26use rustc_session::lint::BuiltinLintDiag;
27use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
28use rustc_span::edition::Edition;
29use rustc_span::source_map::{self, Spanned};
30use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, sym};
31use thin_vec::{ThinVec, thin_vec};
32use tracing::instrument;
33
34use super::diagnostics::SnapshotParser;
35use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
36use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
37use super::{
38    AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle,
39    Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos,
40};
41use crate::{errors, exp, maybe_recover_from_interpolated_ty_qpath};
42
43#[derive(Debug)]
44pub(super) enum DestructuredFloat {
45    /// 1e2
46    Single(Symbol, Span),
47    /// 1.
48    TrailingDot(Symbol, Span, Span),
49    /// 1.2 | 1.2e3
50    MiddleDot(Symbol, Span, Span, Symbol, Span),
51    /// Invalid
52    Error,
53}
54
55impl<'a> Parser<'a> {
56    /// Parses an expression.
57    #[inline]
58    pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> {
59        self.current_closure.take();
60
61        let attrs = self.parse_outer_attributes()?;
62        self.parse_expr_res(Restrictions::empty(), attrs).map(|res| res.0)
63    }
64
65    /// Parses an expression, forcing tokens to be collected.
66    pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box<Expr>> {
67        self.current_closure.take();
68
69        // If the expression is associative (e.g. `1 + 2`), then any preceding
70        // outer attribute actually belongs to the first inner sub-expression.
71        // In which case we must use the pre-attr pos to include the attribute
72        // in the collected tokens for the outer expression.
73        let pre_attr_pos = self.collect_pos();
74        let attrs = self.parse_outer_attributes()?;
75        self.collect_tokens(
76            Some(pre_attr_pos),
77            AttrWrapper::empty(),
78            ForceCollect::Yes,
79            |this, _empty_attrs| {
80                let (expr, is_assoc) = this.parse_expr_res(Restrictions::empty(), attrs)?;
81                let use_pre_attr_pos =
82                    if is_assoc { UsePreAttrPos::Yes } else { UsePreAttrPos::No };
83                Ok((expr, Trailing::No, use_pre_attr_pos))
84            },
85        )
86    }
87
88    pub fn parse_expr_anon_const(
89        &mut self,
90        mgca_disambiguation: impl FnOnce(&Self, &Expr) -> MgcaDisambiguation,
91    ) -> PResult<'a, AnonConst> {
92        self.parse_expr().map(|value| AnonConst {
93            id: DUMMY_NODE_ID,
94            mgca_disambiguation: mgca_disambiguation(self, &value),
95            value,
96        })
97    }
98
99    fn parse_expr_catch_underscore(
100        &mut self,
101        restrictions: Restrictions,
102    ) -> PResult<'a, Box<Expr>> {
103        let attrs = self.parse_outer_attributes()?;
104        match self.parse_expr_res(restrictions, attrs) {
105            Ok((expr, _)) => Ok(expr),
106            Err(err) => match self.token.ident() {
107                Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No))
108                    if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
109                {
110                    // Special-case handling of `foo(_, _, _)`
111                    let guar = err.emit();
112                    self.bump();
113                    Ok(self.mk_expr(self.prev_token.span, ExprKind::Err(guar)))
114                }
115                _ => Err(err),
116            },
117        }
118    }
119
120    /// Parses a sequence of expressions delimited by parentheses.
121    fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<Box<Expr>>> {
122        self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty()))
123            .map(|(r, _)| r)
124    }
125
126    /// Parses an expression, subject to the given restrictions.
127    #[inline]
128    pub(super) fn parse_expr_res(
129        &mut self,
130        r: Restrictions,
131        attrs: AttrWrapper,
132    ) -> PResult<'a, (Box<Expr>, bool)> {
133        self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs))
134    }
135
136    /// Parses an associative expression with operators of at least `min_prec` precedence.
137    /// The `bool` in the return value indicates if it was an assoc expr, i.e. with an operator
138    /// followed by a subexpression (e.g. `1 + 2`).
139    pub(super) fn parse_expr_assoc_with(
140        &mut self,
141        min_prec: Bound<ExprPrecedence>,
142        attrs: AttrWrapper,
143    ) -> PResult<'a, (Box<Expr>, bool)> {
144        let lhs = if self.token.is_range_separator() {
145            return self.parse_expr_prefix_range(attrs).map(|res| (res, false));
146        } else {
147            self.parse_expr_prefix(attrs)?
148        };
149        self.parse_expr_assoc_rest_with(min_prec, false, lhs)
150    }
151
152    /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators
153    /// of at least `min_prec` precedence. The `bool` in the return value indicates if something
154    /// was actually parsed.
155    pub(super) fn parse_expr_assoc_rest_with(
156        &mut self,
157        min_prec: Bound<ExprPrecedence>,
158        starts_stmt: bool,
159        mut lhs: Box<Expr>,
160    ) -> PResult<'a, (Box<Expr>, bool)> {
161        let mut parsed_something = false;
162        if !self.should_continue_as_assoc_expr(&lhs) {
163            return Ok((lhs, parsed_something));
164        }
165
166        self.expected_token_types.insert(TokenType::Operator);
167        while let Some(op) = self.check_assoc_op() {
168            let lhs_span = self.interpolated_or_expr_span(&lhs);
169            let cur_op_span = self.token.span;
170            let restrictions = if op.node.is_assign_like() {
171                self.restrictions & Restrictions::NO_STRUCT_LITERAL
172            } else {
173                self.restrictions
174            };
175            let prec = op.node.precedence();
176            if match min_prec {
177                Bound::Included(min_prec) => prec < min_prec,
178                Bound::Excluded(min_prec) => prec <= min_prec,
179                Bound::Unbounded => false,
180            } {
181                break;
182            }
183            // Check for deprecated `...` syntax
184            if self.token == token::DotDotDot && op.node == AssocOp::Range(RangeLimits::Closed) {
185                self.err_dotdotdot_syntax(self.token.span);
186            }
187
188            if self.token == token::LArrow {
189                self.err_larrow_operator(self.token.span);
190            }
191
192            parsed_something = true;
193            self.bump();
194            if op.node.is_comparison() {
195                if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
196                    return Ok((expr, parsed_something));
197                }
198            }
199
200            // Look for JS' `===` and `!==` and recover
201            if let AssocOp::Binary(bop @ BinOpKind::Eq | bop @ BinOpKind::Ne) = op.node
202                && self.token == token::Eq
203                && self.prev_token.span.hi() == self.token.span.lo()
204            {
205                let sp = op.span.to(self.token.span);
206                let sugg = bop.as_str().into();
207                let invalid = format!("{sugg}=");
208                self.dcx().emit_err(errors::InvalidComparisonOperator {
209                    span: sp,
210                    invalid: invalid.clone(),
211                    sub: errors::InvalidComparisonOperatorSub::Correctable {
212                        span: sp,
213                        invalid,
214                        correct: sugg,
215                    },
216                });
217                self.bump();
218            }
219
220            // Look for PHP's `<>` and recover
221            if op.node == AssocOp::Binary(BinOpKind::Lt)
222                && self.token == token::Gt
223                && self.prev_token.span.hi() == self.token.span.lo()
224            {
225                let sp = op.span.to(self.token.span);
226                self.dcx().emit_err(errors::InvalidComparisonOperator {
227                    span: sp,
228                    invalid: "<>".into(),
229                    sub: errors::InvalidComparisonOperatorSub::Correctable {
230                        span: sp,
231                        invalid: "<>".into(),
232                        correct: "!=".into(),
233                    },
234                });
235                self.bump();
236            }
237
238            // Look for C++'s `<=>` and recover
239            if op.node == AssocOp::Binary(BinOpKind::Le)
240                && self.token == token::Gt
241                && self.prev_token.span.hi() == self.token.span.lo()
242            {
243                let sp = op.span.to(self.token.span);
244                self.dcx().emit_err(errors::InvalidComparisonOperator {
245                    span: sp,
246                    invalid: "<=>".into(),
247                    sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
248                });
249                self.bump();
250            }
251
252            if self.prev_token == token::Plus
253                && self.token == token::Plus
254                && self.prev_token.span.between(self.token.span).is_empty()
255            {
256                let op_span = self.prev_token.span.to(self.token.span);
257                // Eat the second `+`
258                self.bump();
259                lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
260                continue;
261            }
262
263            if self.prev_token == token::Minus
264                && self.token == token::Minus
265                && self.prev_token.span.between(self.token.span).is_empty()
266                && !self.look_ahead(1, |tok| tok.can_begin_expr())
267            {
268                let op_span = self.prev_token.span.to(self.token.span);
269                // Eat the second `-`
270                self.bump();
271                lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
272                continue;
273            }
274
275            let op_span = op.span;
276            let op = op.node;
277            // Special cases:
278            if op == AssocOp::Cast {
279                lhs = self.parse_assoc_op_cast(lhs, lhs_span, op_span, ExprKind::Cast)?;
280                continue;
281            } else if let AssocOp::Range(limits) = op {
282                // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
283                // generalise it to the Fixity::None code.
284                lhs = self.parse_expr_range(prec, lhs, limits, cur_op_span)?;
285                break;
286            }
287
288            let min_prec = match op.fixity() {
289                Fixity::Right => Bound::Included(prec),
290                Fixity::Left | Fixity::None => Bound::Excluded(prec),
291            };
292            let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
293                let attrs = this.parse_outer_attributes()?;
294                this.parse_expr_assoc_with(min_prec, attrs)
295            })?;
296
297            let span = self.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span);
298            lhs = match op {
299                AssocOp::Binary(ast_op) => {
300                    let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs);
301                    self.mk_expr(span, binary)
302                }
303                AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
304                AssocOp::AssignOp(aop) => {
305                    let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs);
306                    self.mk_expr(span, aopexpr)
307                }
308                AssocOp::Cast | AssocOp::Range(_) => {
309                    self.dcx().span_bug(span, "AssocOp should have been handled by special case")
310                }
311            };
312        }
313
314        Ok((lhs, parsed_something))
315    }
316
317    fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
318        match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
319            // Semi-statement forms are odd:
320            // See https://github.com/rust-lang/rust/issues/29071
321            (true, None) => false,
322            (false, _) => true, // Continue parsing the expression.
323            // An exhaustive check is done in the following block, but these are checked first
324            // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
325            // want to keep their span info to improve diagnostics in these cases in a later stage.
326            (true, Some(AssocOp::Binary(
327                BinOpKind::Mul | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
328                BinOpKind::Sub | // `{ 42 } -5`
329                BinOpKind::Add | // `{ 42 } + 42` (unary plus)
330                BinOpKind::And | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
331                BinOpKind::Or | // `{ 42 } || 42` ("logical or" or closure)
332                BinOpKind::BitOr // `{ 42 } | 42` or `{ 42 } |x| 42`
333            ))) => {
334                // These cases are ambiguous and can't be identified in the parser alone.
335                //
336                // Bitwise AND is left out because guessing intent is hard. We can make
337                // suggestions based on the assumption that double-refs are rarely intentional,
338                // and closures are distinct enough that they don't get mixed up with their
339                // return value.
340                let sp = self.psess.source_map().start_point(self.token.span);
341                self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
342                false
343            }
344            (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
345            (true, Some(_)) => {
346                self.error_found_expr_would_be_stmt(lhs);
347                true
348            }
349        }
350    }
351
352    /// We've found an expression that would be parsed as a statement,
353    /// but the next token implies this should be parsed as an expression.
354    /// For example: `if let Some(x) = x { x } else { 0 } / 2`.
355    fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
356        self.dcx().emit_err(errors::FoundExprWouldBeStmt {
357            span: self.token.span,
358            token: self.token,
359            suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
360        });
361    }
362
363    /// Possibly translate the current token to an associative operator.
364    /// The method does not advance the current token.
365    ///
366    /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
367    pub(super) fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
368        let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
369            // When parsing const expressions, stop parsing when encountering `>`.
370            (
371                Some(
372                    AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge)
373                    | AssocOp::AssignOp(AssignOpKind::ShrAssign),
374                ),
375                _,
376            ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
377                return None;
378            }
379            // When recovering patterns as expressions, stop parsing when encountering an
380            // assignment `=`, an alternative `|`, or a range `..`.
381            (
382                Some(
383                    AssocOp::Assign
384                    | AssocOp::AssignOp(_)
385                    | AssocOp::Binary(BinOpKind::BitOr)
386                    | AssocOp::Range(_),
387                ),
388                _,
389            ) if self.restrictions.contains(Restrictions::IS_PAT) => {
390                return None;
391            }
392            (Some(op), _) => (op, self.token.span),
393            (None, Some((Ident { name: sym::and, span }, IdentIsRaw::No)))
394                if self.may_recover() =>
395            {
396                self.dcx().emit_err(errors::InvalidLogicalOperator {
397                    span: self.token.span,
398                    incorrect: "and".into(),
399                    sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
400                });
401                (AssocOp::Binary(BinOpKind::And), span)
402            }
403            (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
404                self.dcx().emit_err(errors::InvalidLogicalOperator {
405                    span: self.token.span,
406                    incorrect: "or".into(),
407                    sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
408                });
409                (AssocOp::Binary(BinOpKind::Or), span)
410            }
411            _ => return None,
412        };
413        Some(source_map::respan(span, op))
414    }
415
416    /// Checks if this expression is a successfully parsed statement.
417    fn expr_is_complete(&self, e: &Expr) -> bool {
418        self.restrictions.contains(Restrictions::STMT_EXPR) && classify::expr_is_complete(e)
419    }
420
421    /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
422    /// The other two variants are handled in `parse_prefix_range_expr` below.
423    fn parse_expr_range(
424        &mut self,
425        prec: ExprPrecedence,
426        lhs: Box<Expr>,
427        limits: RangeLimits,
428        cur_op_span: Span,
429    ) -> PResult<'a, Box<Expr>> {
430        let rhs = if self.is_at_start_of_range_notation_rhs() {
431            let maybe_lt = self.token;
432            let attrs = self.parse_outer_attributes()?;
433            Some(
434                self.parse_expr_assoc_with(Bound::Excluded(prec), attrs)
435                    .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?
436                    .0,
437            )
438        } else {
439            None
440        };
441        let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
442        let span = self.mk_expr_sp(&lhs, lhs.span, cur_op_span, rhs_span);
443        let range = self.mk_range(Some(lhs), rhs, limits);
444        Ok(self.mk_expr(span, range))
445    }
446
447    fn is_at_start_of_range_notation_rhs(&self) -> bool {
448        if self.token.can_begin_expr() {
449            // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
450            if self.token == token::OpenBrace {
451                return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
452            }
453            true
454        } else {
455            false
456        }
457    }
458
459    /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
460    fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
461        if !attrs.is_empty() {
462            let err = errors::DotDotRangeAttribute { span: self.token.span };
463            self.dcx().emit_err(err);
464        }
465
466        // Check for deprecated `...` syntax.
467        if self.token == token::DotDotDot {
468            self.err_dotdotdot_syntax(self.token.span);
469        }
470
471        debug_assert!(
472            self.token.is_range_separator(),
473            "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
474            self.token
475        );
476
477        let limits = match self.token.kind {
478            token::DotDot => RangeLimits::HalfOpen,
479            _ => RangeLimits::Closed,
480        };
481        let op = AssocOp::from_token(&self.token);
482        let attrs = self.parse_outer_attributes()?;
483        self.collect_tokens_for_expr(attrs, |this, attrs| {
484            let lo = this.token.span;
485            let maybe_lt = this.look_ahead(1, |t| t.clone());
486            this.bump();
487            let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
488                // RHS must be parsed with more associativity than the dots.
489                let attrs = this.parse_outer_attributes()?;
490                this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs)
491                    .map(|(x, _)| (lo.to(x.span), Some(x)))
492                    .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
493            } else {
494                (lo, None)
495            };
496            let range = this.mk_range(None, opt_end, limits);
497            Ok(this.mk_expr_with_attrs(span, range, attrs))
498        })
499    }
500
501    /// Parses a prefix-unary-operator expr.
502    fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
503        let lo = self.token.span;
504
505        macro_rules! make_it {
506            ($this:ident, $attrs:expr, |this, _| $body:expr) => {
507                $this.collect_tokens_for_expr($attrs, |$this, attrs| {
508                    let (hi, ex) = $body?;
509                    Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs))
510                })
511            };
512        }
513
514        let this = self;
515
516        // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
517        match this.token.uninterpolate().kind {
518            // `!expr`
519            token::Bang => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
520            // `~expr`
521            token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
522            // `-expr`
523            token::Minus => {
524                make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
525            }
526            // `*expr`
527            token::Star => {
528                make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
529            }
530            // `&expr` and `&&expr`
531            token::And | token::AndAnd => {
532                make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
533            }
534            // `+lit`
535            token::Plus if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
536                let mut err = errors::LeadingPlusNotSupported {
537                    span: lo,
538                    remove_plus: None,
539                    add_parentheses: None,
540                };
541
542                // a block on the LHS might have been intended to be an expression instead
543                if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
544                    err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
545                } else {
546                    err.remove_plus = Some(lo);
547                }
548                this.dcx().emit_err(err);
549
550                this.bump();
551                let attrs = this.parse_outer_attributes()?;
552                this.parse_expr_prefix(attrs)
553            }
554            // Recover from `++x`:
555            token::Plus if this.look_ahead(1, |t| *t == token::Plus) => {
556                let starts_stmt =
557                    this.prev_token == token::Semi || this.prev_token == token::CloseBrace;
558                let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
559                // Eat both `+`s.
560                this.bump();
561                this.bump();
562
563                let operand_expr = this.parse_expr_dot_or_call(attrs)?;
564                this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
565            }
566            token::Ident(..) if this.token.is_keyword(kw::Box) => {
567                make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
568            }
569            token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
570                make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
571            }
572            _ => return this.parse_expr_dot_or_call(attrs),
573        }
574    }
575
576    fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, Box<Expr>)> {
577        self.bump();
578        let attrs = self.parse_outer_attributes()?;
579        let expr = if self.token.is_range_separator() {
580            self.parse_expr_prefix_range(attrs)
581        } else {
582            self.parse_expr_prefix(attrs)
583        }?;
584        let span = self.interpolated_or_expr_span(&expr);
585        Ok((lo.to(span), expr))
586    }
587
588    fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
589        let (span, expr) = self.parse_expr_prefix_common(lo)?;
590        Ok((span, self.mk_unary(op, expr)))
591    }
592
593    /// Recover on `~expr` in favor of `!expr`.
594    fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
595        self.dcx().emit_err(errors::TildeAsUnaryOperator(lo));
596
597        self.parse_expr_unary(lo, UnOp::Not)
598    }
599
600    /// Parse `box expr` - this syntax has been removed, but we still parse this
601    /// for now to provide a more useful error
602    fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
603        let (span, expr) = self.parse_expr_prefix_common(box_kw)?;
604        // Make a multipart suggestion instead of `span_to_snippet` in case source isn't available
605        let box_kw_and_lo = box_kw.until(self.interpolated_or_expr_span(&expr));
606        let hi = span.shrink_to_hi();
607        let sugg = errors::AddBoxNew { box_kw_and_lo, hi };
608        let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span, sugg });
609        Ok((span, ExprKind::Err(guar)))
610    }
611
612    fn is_mistaken_not_ident_negation(&self) -> bool {
613        let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
614            // These tokens can start an expression after `!`, but
615            // can't continue an expression after an ident
616            token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
617            token::Literal(..) | token::Pound => true,
618            _ => t.is_metavar_expr(),
619        };
620        self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr)
621    }
622
623    /// Recover on `not expr` in favor of `!expr`.
624    fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
625        let negated_token = self.look_ahead(1, |t| *t);
626
627        let sub_diag = if negated_token.is_numeric_lit() {
628            errors::NotAsNegationOperatorSub::SuggestNotBitwise
629        } else if negated_token.is_bool_lit() {
630            errors::NotAsNegationOperatorSub::SuggestNotLogical
631        } else {
632            errors::NotAsNegationOperatorSub::SuggestNotDefault
633        };
634
635        self.dcx().emit_err(errors::NotAsNegationOperator {
636            negated: negated_token.span,
637            negated_desc: super::token_descr(&negated_token),
638            // Span the `not` plus trailing whitespace to avoid
639            // trailing whitespace after the `!` in our suggestion
640            sub: sub_diag(
641                self.psess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
642            ),
643        });
644
645        self.parse_expr_unary(lo, UnOp::Not)
646    }
647
648    /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
649    fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
650        match self.prev_token.kind {
651            token::NtIdent(..) | token::NtLifetime(..) => self.prev_token.span,
652            token::CloseInvisible(InvisibleOrigin::MetaVar(_)) => {
653                // `expr.span` is the interpolated span, because invisible open
654                // and close delims both get marked with the same span, one
655                // that covers the entire thing between them. (See
656                // `rustc_expand::mbe::transcribe::transcribe`.)
657                self.prev_token.span
658            }
659            _ => expr.span,
660        }
661    }
662
663    fn parse_assoc_op_cast(
664        &mut self,
665        lhs: Box<Expr>,
666        lhs_span: Span,
667        op_span: Span,
668        expr_kind: fn(Box<Expr>, Box<Ty>) -> ExprKind,
669    ) -> PResult<'a, Box<Expr>> {
670        let mk_expr = |this: &mut Self, lhs: Box<Expr>, rhs: Box<Ty>| {
671            this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs))
672        };
673
674        // Save the state of the parser before parsing type normally, in case there is a
675        // LessThan comparison after this cast.
676        let parser_snapshot_before_type = self.clone();
677        let cast_expr = match self.parse_as_cast_ty() {
678            Ok(rhs) => mk_expr(self, lhs, rhs),
679            Err(type_err) => {
680                if !self.may_recover() {
681                    return Err(type_err);
682                }
683
684                // Rewind to before attempting to parse the type with generics, to recover
685                // from situations like `x as usize < y` in which we first tried to parse
686                // `usize < y` as a type with generic arguments.
687                let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type);
688
689                // Check for typo of `'a: loop { break 'a }` with a missing `'`.
690                match (&lhs.kind, &self.token.kind) {
691                    (
692                        // `foo: `
693                        ExprKind::Path(None, ast::Path { segments, .. }),
694                        token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
695                    ) if let [segment] = segments.as_slice() => {
696                        let snapshot = self.create_snapshot_for_diagnostic();
697                        let label = Label {
698                            ident: Ident::from_str_and_span(
699                                &format!("'{}", segment.ident),
700                                segment.ident.span,
701                            ),
702                        };
703                        match self.parse_expr_labeled(label, false) {
704                            Ok(expr) => {
705                                type_err.cancel();
706                                self.dcx().emit_err(errors::MalformedLoopLabel {
707                                    span: label.ident.span,
708                                    suggestion: label.ident.span.shrink_to_lo(),
709                                });
710                                return Ok(expr);
711                            }
712                            Err(err) => {
713                                err.cancel();
714                                self.restore_snapshot(snapshot);
715                            }
716                        }
717                    }
718                    _ => {}
719                }
720
721                match self.parse_path(PathStyle::Expr) {
722                    Ok(path) => {
723                        let span_after_type = parser_snapshot_after_type.token.span;
724                        let expr = mk_expr(
725                            self,
726                            lhs,
727                            self.mk_ty(path.span, TyKind::Path(None, path.clone())),
728                        );
729
730                        let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
731                        let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg {
732                            left: expr.span.shrink_to_lo(),
733                            right: expr.span.shrink_to_hi(),
734                        };
735
736                        match self.token.kind {
737                            token::Lt => {
738                                self.dcx().emit_err(errors::ComparisonInterpretedAsGeneric {
739                                    comparison: self.token.span,
740                                    r#type: path,
741                                    args: args_span,
742                                    suggestion,
743                                })
744                            }
745                            token::Shl => self.dcx().emit_err(errors::ShiftInterpretedAsGeneric {
746                                shift: self.token.span,
747                                r#type: path,
748                                args: args_span,
749                                suggestion,
750                            }),
751                            _ => {
752                                // We can end up here even without `<` being the next token, for
753                                // example because `parse_ty_no_plus` returns `Err` on keywords,
754                                // but `parse_path` returns `Ok` on them due to error recovery.
755                                // Return original error and parser state.
756                                *self = parser_snapshot_after_type;
757                                return Err(type_err);
758                            }
759                        };
760
761                        // Successfully parsed the type path leaving a `<` yet to parse.
762                        type_err.cancel();
763
764                        // Keep `x as usize` as an expression in AST and continue parsing.
765                        expr
766                    }
767                    Err(path_err) => {
768                        // Couldn't parse as a path, return original error and parser state.
769                        path_err.cancel();
770                        *self = parser_snapshot_after_type;
771                        return Err(type_err);
772                    }
773                }
774            }
775        };
776
777        // Try to parse a postfix operator such as `.`, `?`, or index (`[]`)
778        // after a cast. If one is present, emit an error then return a valid
779        // parse tree; For something like `&x as T[0]` will be as if it was
780        // written `((&x) as T)[0]`.
781
782        let span = cast_expr.span;
783
784        let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?;
785
786        // Check if an illegal postfix operator has been added after the cast.
787        // If the resulting expression is not a cast, it is an illegal postfix operator.
788        if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) {
789            let msg = format!(
790                "cast cannot be followed by {}",
791                match with_postfix.kind {
792                    ExprKind::Index(..) => "indexing",
793                    ExprKind::Try(_) => "`?`",
794                    ExprKind::Field(_, _) => "a field access",
795                    ExprKind::MethodCall(_) => "a method call",
796                    ExprKind::Call(_, _) => "a function call",
797                    ExprKind::Await(_, _) => "`.await`",
798                    ExprKind::Use(_, _) => "`.use`",
799                    ExprKind::Yield(YieldKind::Postfix(_)) => "`.yield`",
800                    ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match",
801                    ExprKind::Err(_) => return Ok(with_postfix),
802                    _ => unreachable!(
803                        "did not expect {:?} as an illegal postfix operator following cast",
804                        with_postfix.kind
805                    ),
806                }
807            );
808            let mut err = self.dcx().struct_span_err(span, msg);
809
810            let suggest_parens = |err: &mut Diag<'_>| {
811                let suggestions = vec![
812                    (span.shrink_to_lo(), "(".to_string()),
813                    (span.shrink_to_hi(), ")".to_string()),
814                ];
815                err.multipart_suggestion(
816                    "try surrounding the expression in parentheses",
817                    suggestions,
818                    Applicability::MachineApplicable,
819                );
820            };
821
822            suggest_parens(&mut err);
823
824            err.emit();
825        };
826        Ok(with_postfix)
827    }
828
829    /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
830    fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
831        self.expect_and()?;
832        let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
833        let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
834        let (borrow_kind, mutbl) = self.parse_borrow_modifiers();
835        let attrs = self.parse_outer_attributes()?;
836        let expr = if self.token.is_range_separator() {
837            self.parse_expr_prefix_range(attrs)
838        } else {
839            self.parse_expr_prefix(attrs)
840        }?;
841        let hi = self.interpolated_or_expr_span(&expr);
842        let span = lo.to(hi);
843        if let Some(lt) = lifetime {
844            self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span));
845        }
846
847        // Add expected tokens if we parsed `&raw` as an expression.
848        // This will make sure we see "expected `const`, `mut`", and
849        // guides recovery in case we write `&raw expr`.
850        if borrow_kind == ast::BorrowKind::Ref
851            && mutbl == ast::Mutability::Not
852            && matches!(&expr.kind, ExprKind::Path(None, p) if *p == kw::Raw)
853        {
854            self.expected_token_types.insert(TokenType::KwMut);
855            self.expected_token_types.insert(TokenType::KwConst);
856        }
857
858        Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
859    }
860
861    fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
862        self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
863    }
864
865    /// Parse `mut?` or `[ raw | pin ] [ const | mut ]`.
866    fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
867        if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) {
868            // `raw [ const | mut ]`.
869            let found_raw = self.eat_keyword(exp!(Raw));
870            assert!(found_raw);
871            let mutability = self.parse_const_or_mut().unwrap();
872            (ast::BorrowKind::Raw, mutability)
873        } else {
874            match self.parse_pin_and_mut() {
875                // `mut?`
876                (ast::Pinnedness::Not, mutbl) => (ast::BorrowKind::Ref, mutbl),
877                // `pin [ const | mut ]`.
878                // `pin` has been gated in `self.parse_pin_and_mut()` so we don't
879                // need to gate it here.
880                (ast::Pinnedness::Pinned, mutbl) => (ast::BorrowKind::Pin, mutbl),
881            }
882        }
883    }
884
885    /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
886    fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
887        self.collect_tokens_for_expr(attrs, |this, attrs| {
888            let base = this.parse_expr_bottom()?;
889            let span = this.interpolated_or_expr_span(&base);
890            this.parse_expr_dot_or_call_with(attrs, base, span)
891        })
892    }
893
894    pub(super) fn parse_expr_dot_or_call_with(
895        &mut self,
896        mut attrs: ast::AttrVec,
897        mut e: Box<Expr>,
898        lo: Span,
899    ) -> PResult<'a, Box<Expr>> {
900        let mut res = ensure_sufficient_stack(|| {
901            loop {
902                let has_question =
903                    if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
904                        // We are using noexpect here because we don't expect a `?` directly after
905                        // a `return` which could be suggested otherwise.
906                        self.eat_noexpect(&token::Question)
907                    } else {
908                        self.eat(exp!(Question))
909                    };
910                if has_question {
911                    // `expr?`
912                    e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
913                    continue;
914                }
915                let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
916                    // We are using noexpect here because we don't expect a `.` directly after
917                    // a `return` which could be suggested otherwise.
918                    self.eat_noexpect(&token::Dot)
919                } else if self.token == TokenKind::RArrow && self.may_recover() {
920                    // Recovery for `expr->suffix`.
921                    self.bump();
922                    let span = self.prev_token.span;
923                    self.dcx().emit_err(errors::ExprRArrowCall { span });
924                    true
925                } else {
926                    self.eat(exp!(Dot))
927                };
928                if has_dot {
929                    // expr.f
930                    e = self.parse_dot_suffix_expr(lo, e)?;
931                    continue;
932                }
933                if self.expr_is_complete(&e) {
934                    return Ok(e);
935                }
936                e = match self.token.kind {
937                    token::OpenParen => self.parse_expr_fn_call(lo, e),
938                    token::OpenBracket => self.parse_expr_index(lo, e)?,
939                    _ => return Ok(e),
940                }
941            }
942        });
943
944        // Stitch the list of outer attributes onto the return value. A little
945        // bit ugly, but the best way given the current code structure.
946        if !attrs.is_empty()
947            && let Ok(expr) = &mut res
948        {
949            mem::swap(&mut expr.attrs, &mut attrs);
950            expr.attrs.extend(attrs)
951        }
952        res
953    }
954
955    pub(super) fn parse_dot_suffix_expr(
956        &mut self,
957        lo: Span,
958        base: Box<Expr>,
959    ) -> PResult<'a, Box<Expr>> {
960        // At this point we've consumed something like `expr.` and `self.token` holds the token
961        // after the dot.
962        match self.token.uninterpolate().kind {
963            token::Ident(..) => self.parse_dot_suffix(base, lo),
964            token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
965                let ident_span = self.token.span;
966                self.bump();
967                Ok(self.mk_expr_tuple_field_access(lo, ident_span, base, symbol, suffix))
968            }
969            token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
970                Ok(match self.break_up_float(symbol, self.token.span) {
971                    // 1e2
972                    DestructuredFloat::Single(sym, _sp) => {
973                        // `foo.1e2`: a single complete dot access, fully consumed. We end up with
974                        // the `1e2` token in `self.prev_token` and the following token in
975                        // `self.token`.
976                        let ident_span = self.token.span;
977                        self.bump();
978                        self.mk_expr_tuple_field_access(lo, ident_span, base, sym, suffix)
979                    }
980                    // 1.
981                    DestructuredFloat::TrailingDot(sym, ident_span, dot_span) => {
982                        // `foo.1.`: a single complete dot access and the start of another.
983                        // We end up with the `sym` (`1`) token in `self.prev_token` and a dot in
984                        // `self.token`.
985                        assert!(suffix.is_none());
986                        self.token = Token::new(token::Ident(sym, IdentIsRaw::No), ident_span);
987                        self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing));
988                        self.mk_expr_tuple_field_access(lo, ident_span, base, sym, None)
989                    }
990                    // 1.2 | 1.2e3
991                    DestructuredFloat::MiddleDot(
992                        sym1,
993                        ident1_span,
994                        _dot_span,
995                        sym2,
996                        ident2_span,
997                    ) => {
998                        // `foo.1.2` (or `foo.1.2e3`): two complete dot accesses. We end up with
999                        // the `sym2` (`2` or `2e3`) token in `self.prev_token` and the following
1000                        // token in `self.token`.
1001                        let next_token2 =
1002                            Token::new(token::Ident(sym2, IdentIsRaw::No), ident2_span);
1003                        self.bump_with((next_token2, self.token_spacing));
1004                        self.bump();
1005                        let base1 =
1006                            self.mk_expr_tuple_field_access(lo, ident1_span, base, sym1, None);
1007                        self.mk_expr_tuple_field_access(lo, ident2_span, base1, sym2, suffix)
1008                    }
1009                    DestructuredFloat::Error => base,
1010                })
1011            }
1012            _ => {
1013                self.error_unexpected_after_dot();
1014                Ok(base)
1015            }
1016        }
1017    }
1018
1019    fn error_unexpected_after_dot(&self) {
1020        let actual = super::token_descr(&self.token);
1021        let span = self.token.span;
1022        let sm = self.psess.source_map();
1023        let (span, actual) = match (&self.token.kind, self.subparser_name) {
1024            (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => {
1025                (span.shrink_to_hi(), format!("`{}`", snippet))
1026            }
1027            (token::CloseInvisible(InvisibleOrigin::MetaVar(_)), _) => {
1028                // No need to report an error. This case will only occur when parsing a pasted
1029                // metavariable, and we should have emitted an error when parsing the macro call in
1030                // the first place. E.g. in this code:
1031                // ```
1032                // macro_rules! m { ($e:expr) => { $e }; }
1033                //
1034                // fn main() {
1035                //     let f = 1;
1036                //     m!(f.);
1037                // }
1038                // ```
1039                // we'll get an error "unexpected token: `)` when parsing the `m!(f.)`, so we don't
1040                // want to issue a second error when parsing the expansion `«f.»` (where `«`/`»`
1041                // represent the invisible delimiters).
1042                self.dcx().span_delayed_bug(span, "bad dot expr in metavariable");
1043                return;
1044            }
1045            _ => (span, actual),
1046        };
1047        self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual });
1048    }
1049
1050    /// We need an identifier or integer, but the next token is a float.
1051    /// Break the float into components to extract the identifier or integer.
1052    ///
1053    /// See also [`TokenKind::break_two_token_op`] which does similar splitting of `>>` into `>`.
1054    //
1055    // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2
1056    //  parts unless those parts are processed immediately. `TokenCursor` should either
1057    //  support pushing "future tokens" (would be also helpful to `break_and_eat`), or
1058    //  we should break everything including floats into more basic proc-macro style
1059    //  tokens in the lexer (probably preferable).
1060    pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
1061        #[derive(Debug)]
1062        enum FloatComponent {
1063            IdentLike(String),
1064            Punct(char),
1065        }
1066        use FloatComponent::*;
1067
1068        let float_str = float.as_str();
1069        let mut components = Vec::new();
1070        let mut ident_like = String::new();
1071        for c in float_str.chars() {
1072            if c == '_' || c.is_ascii_alphanumeric() {
1073                ident_like.push(c);
1074            } else if matches!(c, '.' | '+' | '-') {
1075                if !ident_like.is_empty() {
1076                    components.push(IdentLike(mem::take(&mut ident_like)));
1077                }
1078                components.push(Punct(c));
1079            } else {
1080                panic!("unexpected character in a float token: {c:?}")
1081            }
1082        }
1083        if !ident_like.is_empty() {
1084            components.push(IdentLike(ident_like));
1085        }
1086
1087        // With proc macros the span can refer to anything, the source may be too short,
1088        // or too long, or non-ASCII. It only makes sense to break our span into components
1089        // if its underlying text is identical to our float literal.
1090        let can_take_span_apart =
1091            || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref();
1092
1093        match &*components {
1094            // 1e2
1095            [IdentLike(i)] => {
1096                DestructuredFloat::Single(Symbol::intern(i), span)
1097            }
1098            // 1.
1099            [IdentLike(left), Punct('.')] => {
1100                let (left_span, dot_span) = if can_take_span_apart() {
1101                    let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
1102                    let dot_span = span.with_lo(left_span.hi());
1103                    (left_span, dot_span)
1104                } else {
1105                    (span, span)
1106                };
1107                let left = Symbol::intern(left);
1108                DestructuredFloat::TrailingDot(left, left_span, dot_span)
1109            }
1110            // 1.2 | 1.2e3
1111            [IdentLike(left), Punct('.'), IdentLike(right)] => {
1112                let (left_span, dot_span, right_span) = if can_take_span_apart() {
1113                    let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
1114                    let dot_span = span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1));
1115                    let right_span = span.with_lo(dot_span.hi());
1116                    (left_span, dot_span, right_span)
1117                } else {
1118                    (span, span, span)
1119                };
1120                let left = Symbol::intern(left);
1121                let right = Symbol::intern(right);
1122                DestructuredFloat::MiddleDot(left, left_span, dot_span, right, right_span)
1123            }
1124            // 1e+ | 1e- (recovered)
1125            [IdentLike(_), Punct('+' | '-')] |
1126            // 1e+2 | 1e-2
1127            [IdentLike(_), Punct('+' | '-'), IdentLike(_)] |
1128            // 1.2e+ | 1.2e-
1129            [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] |
1130            // 1.2e+3 | 1.2e-3
1131            [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => {
1132                // See the FIXME about `TokenCursor` above.
1133                self.error_unexpected_after_dot();
1134                DestructuredFloat::Error
1135            }
1136            _ => panic!("unexpected components in a float token: {components:?}"),
1137        }
1138    }
1139
1140    /// Parse the field access used in offset_of, matched by `$(e:expr)+`.
1141    /// Currently returns a list of idents. However, it should be possible in
1142    /// future to also do array indices, which might be arbitrary expressions.
1143    fn parse_floating_field_access(&mut self) -> PResult<'a, Vec<Ident>> {
1144        let mut fields = Vec::new();
1145        let mut trailing_dot = None;
1146
1147        loop {
1148            // This is expected to use a metavariable $(args:expr)+, but the builtin syntax
1149            // could be called directly. Calling `parse_expr` allows this function to only
1150            // consider `Expr`s.
1151            let expr = self.parse_expr()?;
1152            let mut current = &expr;
1153            let start_idx = fields.len();
1154            loop {
1155                match current.kind {
1156                    ExprKind::Field(ref left, right) => {
1157                        // Field access is read right-to-left.
1158                        fields.insert(start_idx, right);
1159                        trailing_dot = None;
1160                        current = left;
1161                    }
1162                    // Parse this both to give helpful error messages and to
1163                    // verify it can be done with this parser setup.
1164                    ExprKind::Index(ref left, ref _right, span) => {
1165                        self.dcx().emit_err(errors::ArrayIndexInOffsetOf(span));
1166                        current = left;
1167                    }
1168                    ExprKind::Lit(token::Lit {
1169                        kind: token::Float | token::Integer,
1170                        symbol,
1171                        suffix,
1172                    }) => {
1173                        if let Some(suffix) = suffix {
1174                            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
1175                                span: current.span,
1176                                suffix,
1177                            });
1178                        }
1179                        match self.break_up_float(symbol, current.span) {
1180                            // 1e2
1181                            DestructuredFloat::Single(sym, sp) => {
1182                                trailing_dot = None;
1183                                fields.insert(start_idx, Ident::new(sym, sp));
1184                            }
1185                            // 1.
1186                            DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
1187                                assert!(suffix.is_none());
1188                                trailing_dot = Some(dot_span);
1189                                fields.insert(start_idx, Ident::new(sym, sym_span));
1190                            }
1191                            // 1.2 | 1.2e3
1192                            DestructuredFloat::MiddleDot(
1193                                symbol1,
1194                                span1,
1195                                _dot_span,
1196                                symbol2,
1197                                span2,
1198                            ) => {
1199                                trailing_dot = None;
1200                                fields.insert(start_idx, Ident::new(symbol2, span2));
1201                                fields.insert(start_idx, Ident::new(symbol1, span1));
1202                            }
1203                            DestructuredFloat::Error => {
1204                                trailing_dot = None;
1205                                fields.insert(start_idx, Ident::new(symbol, self.prev_token.span));
1206                            }
1207                        }
1208                        break;
1209                    }
1210                    ExprKind::Path(None, Path { ref segments, .. }) => {
1211                        match &segments[..] {
1212                            [PathSegment { ident, args: None, .. }] => {
1213                                trailing_dot = None;
1214                                fields.insert(start_idx, *ident)
1215                            }
1216                            _ => {
1217                                self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
1218                                break;
1219                            }
1220                        }
1221                        break;
1222                    }
1223                    _ => {
1224                        self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
1225                        break;
1226                    }
1227                }
1228            }
1229
1230            if self.token.kind.close_delim().is_some() || self.token.kind == token::Comma {
1231                break;
1232            } else if trailing_dot.is_none() {
1233                // This loop should only repeat if there is a trailing dot.
1234                self.dcx().emit_err(errors::InvalidOffsetOf(self.token.span));
1235                break;
1236            }
1237        }
1238        if let Some(dot) = trailing_dot {
1239            self.dcx().emit_err(errors::InvalidOffsetOf(dot));
1240        }
1241        Ok(fields.into_iter().collect())
1242    }
1243
1244    fn mk_expr_tuple_field_access(
1245        &self,
1246        lo: Span,
1247        ident_span: Span,
1248        base: Box<Expr>,
1249        field: Symbol,
1250        suffix: Option<Symbol>,
1251    ) -> Box<Expr> {
1252        if let Some(suffix) = suffix {
1253            self.dcx()
1254                .emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix });
1255        }
1256        self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span)))
1257    }
1258
1259    /// Parse a function call expression, `expr(...)`.
1260    fn parse_expr_fn_call(&mut self, lo: Span, fun: Box<Expr>) -> Box<Expr> {
1261        let snapshot = if self.token == token::OpenParen {
1262            Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
1263        } else {
1264            None
1265        };
1266        let open_paren = self.token.span;
1267
1268        let seq = self
1269            .parse_expr_paren_seq()
1270            .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
1271        match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
1272            Ok(expr) => expr,
1273            Err(err) => self.recover_seq_parse_error(exp!(OpenParen), exp!(CloseParen), lo, err),
1274        }
1275    }
1276
1277    /// If we encounter a parser state that looks like the user has written a `struct` literal with
1278    /// parentheses instead of braces, recover the parser state and provide suggestions.
1279    #[instrument(skip(self, seq, snapshot), level = "trace")]
1280    fn maybe_recover_struct_lit_bad_delims(
1281        &mut self,
1282        lo: Span,
1283        open_paren: Span,
1284        seq: PResult<'a, Box<Expr>>,
1285        snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
1286    ) -> PResult<'a, Box<Expr>> {
1287        match (self.may_recover(), seq, snapshot) {
1288            (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
1289                snapshot.bump(); // `(`
1290                match snapshot.parse_struct_fields(path.clone(), false, exp!(CloseParen)) {
1291                    Ok((fields, ..)) if snapshot.eat(exp!(CloseParen)) => {
1292                        // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
1293                        // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
1294                        self.restore_snapshot(snapshot);
1295                        let close_paren = self.prev_token.span;
1296                        let span = lo.to(close_paren);
1297                        // filter shorthand fields
1298                        let fields: Vec<_> =
1299                            fields.into_iter().filter(|field| !field.is_shorthand).collect();
1300
1301                        let guar = if !fields.is_empty() &&
1302                            // `token.kind` should not be compared here.
1303                            // This is because the `snapshot.token.kind` is treated as the same as
1304                            // that of the open delim in `TokenTreesReader::parse_token_tree`, even
1305                            // if they are different.
1306                            self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
1307                        {
1308                            err.cancel();
1309                            self.dcx()
1310                                .create_err(errors::ParenthesesWithStructFields {
1311                                    span,
1312                                    r#type: path,
1313                                    braces_for_struct: errors::BracesForStructLiteral {
1314                                        first: open_paren,
1315                                        second: close_paren,
1316                                    },
1317                                    no_fields_for_fn: errors::NoFieldsForFnCall {
1318                                        fields: fields
1319                                            .into_iter()
1320                                            .map(|field| field.span.until(field.expr.span))
1321                                            .collect(),
1322                                    },
1323                                })
1324                                .emit()
1325                        } else {
1326                            err.emit()
1327                        };
1328                        Ok(self.mk_expr_err(span, guar))
1329                    }
1330                    Ok(_) => Err(err),
1331                    Err(err2) => {
1332                        err2.cancel();
1333                        Err(err)
1334                    }
1335                }
1336            }
1337            (_, seq, _) => seq,
1338        }
1339    }
1340
1341    /// Parse an indexing expression `expr[...]`.
1342    fn parse_expr_index(&mut self, lo: Span, base: Box<Expr>) -> PResult<'a, Box<Expr>> {
1343        let prev_span = self.prev_token.span;
1344        let open_delim_span = self.token.span;
1345        self.bump(); // `[`
1346        let index = self.parse_expr()?;
1347        self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
1348        self.expect(exp!(CloseBracket))?;
1349        Ok(self.mk_expr(
1350            lo.to(self.prev_token.span),
1351            self.mk_index(base, index, open_delim_span.to(self.prev_token.span)),
1352        ))
1353    }
1354
1355    /// Assuming we have just parsed `.`, continue parsing into an expression.
1356    fn parse_dot_suffix(&mut self, self_arg: Box<Expr>, lo: Span) -> PResult<'a, Box<Expr>> {
1357        if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
1358            return Ok(self.mk_await_expr(self_arg, lo));
1359        }
1360
1361        if self.eat_keyword(exp!(Use)) {
1362            let use_span = self.prev_token.span;
1363            self.psess.gated_spans.gate(sym::ergonomic_clones, use_span);
1364            return Ok(self.mk_use_expr(self_arg, lo));
1365        }
1366
1367        // Post-fix match
1368        if self.eat_keyword(exp!(Match)) {
1369            let match_span = self.prev_token.span;
1370            self.psess.gated_spans.gate(sym::postfix_match, match_span);
1371            return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
1372        }
1373
1374        // Parse a postfix `yield`.
1375        if self.eat_keyword(exp!(Yield)) {
1376            let yield_span = self.prev_token.span;
1377            self.psess.gated_spans.gate(sym::yield_expr, yield_span);
1378            return Ok(
1379                self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg)))
1380            );
1381        }
1382
1383        let fn_span_lo = self.token.span;
1384        let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
1385        self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
1386        self.check_turbofish_missing_angle_brackets(&mut seg);
1387
1388        if self.check(exp!(OpenParen)) {
1389            // Method call `expr.f()`
1390            let args = self.parse_expr_paren_seq()?;
1391            let fn_span = fn_span_lo.to(self.prev_token.span);
1392            let span = lo.to(self.prev_token.span);
1393            Ok(self.mk_expr(
1394                span,
1395                ExprKind::MethodCall(Box::new(ast::MethodCall {
1396                    seg,
1397                    receiver: self_arg,
1398                    args,
1399                    span: fn_span,
1400                })),
1401            ))
1402        } else {
1403            // Field access `expr.f`
1404            let span = lo.to(self.prev_token.span);
1405            if let Some(args) = seg.args {
1406                // See `StashKey::GenericInFieldExpr` for more info on why we stash this.
1407                self.dcx()
1408                    .create_err(errors::FieldExpressionWithGeneric(args.span()))
1409                    .stash(seg.ident.span, StashKey::GenericInFieldExpr);
1410            }
1411
1412            Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
1413        }
1414    }
1415
1416    /// At the bottom (top?) of the precedence hierarchy,
1417    /// Parses things like parenthesized exprs, macros, `return`, etc.
1418    ///
1419    /// N.B., this does not parse outer attributes, and is private because it only works
1420    /// correctly if called from `parse_expr_dot_or_call`.
1421    fn parse_expr_bottom(&mut self) -> PResult<'a, Box<Expr>> {
1422        maybe_recover_from_interpolated_ty_qpath!(self, true);
1423
1424        let span = self.token.span;
1425        if let Some(expr) = self.eat_metavar_seq_with_matcher(
1426            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
1427            |this| {
1428                // Force collection (as opposed to just `parse_expr`) is required to avoid the
1429                // attribute duplication seen in #138478.
1430                let expr = this.parse_expr_force_collect();
1431                // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly
1432                // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line
1433                // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in
1434                // `compiler/rustc_index/src/bit_set/tests.rs`.
1435                if this.token.kind == token::Comma {
1436                    this.bump();
1437                }
1438                expr
1439            },
1440        ) {
1441            return Ok(expr);
1442        } else if let Some(lit) =
1443            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
1444        {
1445            return Ok(lit);
1446        } else if let Some(block) =
1447            self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block())
1448        {
1449            return Ok(self.mk_expr(span, ExprKind::Block(block, None)));
1450        } else if let Some(path) =
1451            self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type))
1452        {
1453            return Ok(self.mk_expr(span, ExprKind::Path(None, path)));
1454        }
1455
1456        // Outer attributes are already parsed and will be
1457        // added to the return value after the fact.
1458
1459        let restrictions = self.restrictions;
1460        self.with_res(restrictions - Restrictions::ALLOW_LET, |this| {
1461            // Note: adding new syntax here? Don't forget to adjust `TokenKind::can_begin_expr()`.
1462            let lo = this.token.span;
1463            if let token::Literal(_) = this.token.kind {
1464                // This match arm is a special-case of the `_` match arm below and
1465                // could be removed without changing functionality, but it's faster
1466                // to have it here, especially for programs with large constants.
1467                this.parse_expr_lit()
1468            } else if this.check(exp!(OpenParen)) {
1469                this.parse_expr_tuple_parens(restrictions)
1470            } else if this.check(exp!(OpenBrace)) {
1471                this.parse_expr_block(None, lo, BlockCheckMode::Default)
1472            } else if this.check(exp!(Or)) || this.check(exp!(OrOr)) {
1473                this.parse_expr_closure().map_err(|mut err| {
1474                    // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
1475                    // then suggest parens around the lhs.
1476                    if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
1477                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
1478                    }
1479                    err
1480                })
1481            } else if this.check(exp!(OpenBracket)) {
1482                this.parse_expr_array_or_repeat(exp!(CloseBracket))
1483            } else if this.is_builtin() {
1484                this.parse_expr_builtin()
1485            } else if this.check_path() {
1486                this.parse_expr_path_start()
1487            } else if this.check_keyword(exp!(Move))
1488                || this.check_keyword(exp!(Use))
1489                || this.check_keyword(exp!(Static))
1490                || this.check_const_closure()
1491            {
1492                this.parse_expr_closure()
1493            } else if this.eat_keyword(exp!(If)) {
1494                this.parse_expr_if()
1495            } else if this.check_keyword(exp!(For)) {
1496                if this.choose_generics_over_qpath(1) {
1497                    this.parse_expr_closure()
1498                } else {
1499                    assert!(this.eat_keyword(exp!(For)));
1500                    this.parse_expr_for(None, lo)
1501                }
1502            } else if this.eat_keyword(exp!(While)) {
1503                this.parse_expr_while(None, lo)
1504            } else if let Some(label) = this.eat_label() {
1505                this.parse_expr_labeled(label, true)
1506            } else if this.eat_keyword(exp!(Loop)) {
1507                this.parse_expr_loop(None, lo).map_err(|mut err| {
1508                    err.span_label(lo, "while parsing this `loop` expression");
1509                    err
1510                })
1511            } else if this.eat_keyword(exp!(Match)) {
1512                this.parse_expr_match().map_err(|mut err| {
1513                    err.span_label(lo, "while parsing this `match` expression");
1514                    err
1515                })
1516            } else if this.eat_keyword(exp!(Unsafe)) {
1517                this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
1518                    |mut err| {
1519                        err.span_label(lo, "while parsing this `unsafe` expression");
1520                        err
1521                    },
1522                )
1523            } else if this.check_inline_const(0) {
1524                this.parse_const_block(lo)
1525            } else if this.may_recover() && this.is_do_catch_block() {
1526                this.recover_do_catch()
1527            } else if this.is_try_block() {
1528                this.expect_keyword(exp!(Try))?;
1529                this.parse_try_block(lo)
1530            } else if this.eat_keyword(exp!(Return)) {
1531                this.parse_expr_return()
1532            } else if this.eat_keyword(exp!(Continue)) {
1533                this.parse_expr_continue(lo)
1534            } else if this.eat_keyword(exp!(Break)) {
1535                this.parse_expr_break()
1536            } else if this.eat_keyword(exp!(Yield)) {
1537                this.parse_expr_yield()
1538            } else if this.is_do_yeet() {
1539                this.parse_expr_yeet()
1540            } else if this.eat_keyword(exp!(Become)) {
1541                this.parse_expr_become()
1542            } else if this.check_keyword(exp!(Let)) {
1543                this.parse_expr_let(restrictions)
1544            } else if this.eat_keyword(exp!(Underscore)) {
1545                Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
1546            } else if this.token_uninterpolated_span().at_least_rust_2018() {
1547                // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
1548                let at_async = this.check_keyword(exp!(Async));
1549                // check for `gen {}` and `gen move {}`
1550                // or `async gen {}` and `async gen move {}`
1551                // FIXME: (async) gen closures aren't yet parsed.
1552                // FIXME(gen_blocks): Parse `gen async` and suggest swap
1553                if this.token_uninterpolated_span().at_least_rust_2024()
1554                    && this.is_gen_block(kw::Gen, at_async as usize)
1555                {
1556                    this.parse_gen_block()
1557                // Check for `async {` and `async move {`,
1558                } else if this.is_gen_block(kw::Async, 0) {
1559                    this.parse_gen_block()
1560                } else if at_async {
1561                    this.parse_expr_closure()
1562                } else if this.eat_keyword_noexpect(kw::Await) {
1563                    this.recover_incorrect_await_syntax(lo)
1564                } else {
1565                    this.parse_expr_lit()
1566                }
1567            } else {
1568                this.parse_expr_lit()
1569            }
1570        })
1571    }
1572
1573    fn parse_expr_lit(&mut self) -> PResult<'a, Box<Expr>> {
1574        let lo = self.token.span;
1575        match self.parse_opt_token_lit() {
1576            Some((token_lit, _)) => {
1577                let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit));
1578                self.maybe_recover_from_bad_qpath(expr)
1579            }
1580            None => self.try_macro_suggestion(),
1581        }
1582    }
1583
1584    fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
1585        let lo = self.token.span;
1586        self.expect(exp!(OpenParen))?;
1587        let (es, trailing_comma) = match self.parse_seq_to_end(
1588            exp!(CloseParen),
1589            SeqSep::trailing_allowed(exp!(Comma)),
1590            |p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)),
1591        ) {
1592            Ok(x) => x,
1593            Err(err) => {
1594                return Ok(self.recover_seq_parse_error(
1595                    exp!(OpenParen),
1596                    exp!(CloseParen),
1597                    lo,
1598                    err,
1599                ));
1600            }
1601        };
1602        let kind = if es.len() == 1 && matches!(trailing_comma, Trailing::No) {
1603            // `(e)` is parenthesized `e`.
1604            ExprKind::Paren(es.into_iter().next().unwrap())
1605        } else {
1606            // `(e,)` is a tuple with only one field, `e`.
1607            ExprKind::Tup(es)
1608        };
1609        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1610        self.maybe_recover_from_bad_qpath(expr)
1611    }
1612
1613    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair) -> PResult<'a, Box<Expr>> {
1614        let lo = self.token.span;
1615        self.bump(); // `[` or other open delim
1616
1617        let kind = if self.eat(close) {
1618            // Empty vector
1619            ExprKind::Array(ThinVec::new())
1620        } else {
1621            // Non-empty vector
1622            let first_expr = self.parse_expr()?;
1623            if self.eat(exp!(Semi)) {
1624                // Repeating array syntax: `[ 0; 512 ]`
1625                let count = if self.eat_keyword(exp!(Const)) {
1626                    // While we could just disambiguate `Direct` from `AnonConst` by
1627                    // treating all const block exprs as `AnonConst`, that would
1628                    // complicate the DefCollector and likely all other visitors.
1629                    // So we strip the const blockiness and just store it as a block
1630                    // in the AST with the extra disambiguator on the AnonConst
1631                    self.parse_mgca_const_block(false)?
1632                } else {
1633                    self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
1634                };
1635                self.expect(close)?;
1636                ExprKind::Repeat(first_expr, count)
1637            } else if self.eat(exp!(Comma)) {
1638                // Vector with two or more elements.
1639                let sep = SeqSep::trailing_allowed(exp!(Comma));
1640                let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?;
1641                exprs.insert(0, first_expr);
1642                ExprKind::Array(exprs)
1643            } else {
1644                // Vector with one element
1645                self.expect(close)?;
1646                ExprKind::Array(thin_vec![first_expr])
1647            }
1648        };
1649        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1650        self.maybe_recover_from_bad_qpath(expr)
1651    }
1652
1653    fn parse_expr_path_start(&mut self) -> PResult<'a, Box<Expr>> {
1654        let maybe_eq_tok = self.prev_token;
1655        let (qself, path) = if self.eat_lt() {
1656            let lt_span = self.prev_token.span;
1657            let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| {
1658                // Suggests using '<=' if there is an error parsing qpath when the previous token
1659                // is an '=' token. Only emits suggestion if the '<' token and '=' token are
1660                // directly adjacent (i.e. '=<')
1661                if maybe_eq_tok == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() {
1662                    let eq_lt = maybe_eq_tok.span.to(lt_span);
1663                    err.span_suggestion(eq_lt, "did you mean", "<=", Applicability::Unspecified);
1664                }
1665                err
1666            })?;
1667            (Some(qself), path)
1668        } else {
1669            (None, self.parse_path(PathStyle::Expr)?)
1670        };
1671
1672        // `!`, as an operator, is prefix, so we know this isn't that.
1673        let (span, kind) = if self.eat(exp!(Bang)) {
1674            // MACRO INVOCATION expression
1675            if qself.is_some() {
1676                self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
1677            }
1678            let lo = path.span;
1679            let mac = Box::new(MacCall { path, args: self.parse_delim_args()? });
1680            (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
1681        } else if self.check(exp!(OpenBrace))
1682            && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
1683        {
1684            if qself.is_some() {
1685                self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
1686            }
1687            return expr;
1688        } else {
1689            (path.span, ExprKind::Path(qself, path))
1690        };
1691
1692        let expr = self.mk_expr(span, kind);
1693        self.maybe_recover_from_bad_qpath(expr)
1694    }
1695
1696    /// Parse `'label: $expr`. The label is already parsed.
1697    pub(super) fn parse_expr_labeled(
1698        &mut self,
1699        label_: Label,
1700        mut consume_colon: bool,
1701    ) -> PResult<'a, Box<Expr>> {
1702        let lo = label_.ident.span;
1703        let label = Some(label_);
1704        let ate_colon = self.eat(exp!(Colon));
1705        let tok_sp = self.token.span;
1706        let expr = if self.eat_keyword(exp!(While)) {
1707            self.parse_expr_while(label, lo)
1708        } else if self.eat_keyword(exp!(For)) {
1709            self.parse_expr_for(label, lo)
1710        } else if self.eat_keyword(exp!(Loop)) {
1711            self.parse_expr_loop(label, lo)
1712        } else if self.check_noexpect(&token::OpenBrace) || self.token.is_metavar_block() {
1713            self.parse_expr_block(label, lo, BlockCheckMode::Default)
1714        } else if !ate_colon
1715            && self.may_recover()
1716            && (self.token.kind.close_delim().is_some() || self.token.is_punct())
1717            && could_be_unclosed_char_literal(label_.ident)
1718        {
1719            let (lit, _) =
1720                self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
1721                    self_.dcx().create_err(errors::UnexpectedTokenAfterLabel {
1722                        span: self_.token.span,
1723                        remove_label: None,
1724                        enclose_in_block: None,
1725                    })
1726                });
1727            consume_colon = false;
1728            Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
1729        } else if !ate_colon
1730            && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
1731        {
1732            // We're probably inside of a `Path<'a>` that needs a turbofish
1733            let guar = self.dcx().emit_err(errors::UnexpectedTokenAfterLabel {
1734                span: self.token.span,
1735                remove_label: None,
1736                enclose_in_block: None,
1737            });
1738            consume_colon = false;
1739            Ok(self.mk_expr_err(lo, guar))
1740        } else {
1741            let mut err = errors::UnexpectedTokenAfterLabel {
1742                span: self.token.span,
1743                remove_label: None,
1744                enclose_in_block: None,
1745            };
1746
1747            // Continue as an expression in an effort to recover on `'label: non_block_expr`.
1748            let expr = self.parse_expr().map(|expr| {
1749                let span = expr.span;
1750
1751                let found_labeled_breaks = {
1752                    struct FindLabeledBreaksVisitor;
1753
1754                    impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
1755                        type Result = ControlFlow<()>;
1756                        fn visit_expr(&mut self, ex: &'ast Expr) -> ControlFlow<()> {
1757                            if let ExprKind::Break(Some(_label), _) = ex.kind {
1758                                ControlFlow::Break(())
1759                            } else {
1760                                walk_expr(self, ex)
1761                            }
1762                        }
1763                    }
1764
1765                    FindLabeledBreaksVisitor.visit_expr(&expr).is_break()
1766                };
1767
1768                // Suggestion involves adding a labeled block.
1769                //
1770                // If there are no breaks that may use this label, suggest removing the label and
1771                // recover to the unmodified expression.
1772                if !found_labeled_breaks {
1773                    err.remove_label = Some(lo.until(span));
1774
1775                    return expr;
1776                }
1777
1778                err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
1779                    left: span.shrink_to_lo(),
1780                    right: span.shrink_to_hi(),
1781                });
1782
1783                // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
1784                let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
1785                let blk = self.mk_block(thin_vec![stmt], BlockCheckMode::Default, span);
1786                self.mk_expr(span, ExprKind::Block(blk, label))
1787            });
1788
1789            self.dcx().emit_err(err);
1790            expr
1791        }?;
1792
1793        if !ate_colon && consume_colon {
1794            self.dcx().emit_err(errors::RequireColonAfterLabeledExpression {
1795                span: expr.span,
1796                label: lo,
1797                label_end: lo.between(tok_sp),
1798            });
1799        }
1800
1801        Ok(expr)
1802    }
1803
1804    /// Emit an error when a char is parsed as a lifetime or label because of a missing quote.
1805    pub(super) fn recover_unclosed_char<L>(
1806        &self,
1807        ident: Ident,
1808        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
1809        err: impl FnOnce(&Self) -> Diag<'a>,
1810    ) -> L {
1811        assert!(could_be_unclosed_char_literal(ident));
1812        self.dcx()
1813            .try_steal_modify_and_emit_err(ident.span, StashKey::LifetimeIsChar, |err| {
1814                err.span_suggestion_verbose(
1815                    ident.span.shrink_to_hi(),
1816                    "add `'` to close the char literal",
1817                    "'",
1818                    Applicability::MaybeIncorrect,
1819                );
1820            })
1821            .unwrap_or_else(|| {
1822                err(self)
1823                    .with_span_suggestion_verbose(
1824                        ident.span.shrink_to_hi(),
1825                        "add `'` to close the char literal",
1826                        "'",
1827                        Applicability::MaybeIncorrect,
1828                    )
1829                    .emit()
1830            });
1831        let name = ident.without_first_quote().name;
1832        mk_lit_char(name, ident.span)
1833    }
1834
1835    /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
1836    fn recover_do_catch(&mut self) -> PResult<'a, Box<Expr>> {
1837        let lo = self.token.span;
1838
1839        self.bump(); // `do`
1840        self.bump(); // `catch`
1841
1842        let span = lo.to(self.prev_token.span);
1843        self.dcx().emit_err(errors::DoCatchSyntaxRemoved { span });
1844
1845        self.parse_try_block(lo)
1846    }
1847
1848    /// Parse an expression if the token can begin one.
1849    fn parse_expr_opt(&mut self) -> PResult<'a, Option<Box<Expr>>> {
1850        Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None })
1851    }
1852
1853    /// Parse `"return" expr?`.
1854    fn parse_expr_return(&mut self) -> PResult<'a, Box<Expr>> {
1855        let lo = self.prev_token.span;
1856        let kind = ExprKind::Ret(self.parse_expr_opt()?);
1857        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
1858        self.maybe_recover_from_bad_qpath(expr)
1859    }
1860
1861    /// Parse `"do" "yeet" expr?`.
1862    fn parse_expr_yeet(&mut self) -> PResult<'a, Box<Expr>> {
1863        let lo = self.token.span;
1864
1865        self.bump(); // `do`
1866        self.bump(); // `yeet`
1867
1868        let kind = ExprKind::Yeet(self.parse_expr_opt()?);
1869
1870        let span = lo.to(self.prev_token.span);
1871        self.psess.gated_spans.gate(sym::yeet_expr, span);
1872        let expr = self.mk_expr(span, kind);
1873        self.maybe_recover_from_bad_qpath(expr)
1874    }
1875
1876    /// Parse `"become" expr`, with `"become"` token already eaten.
1877    fn parse_expr_become(&mut self) -> PResult<'a, Box<Expr>> {
1878        let lo = self.prev_token.span;
1879        let kind = ExprKind::Become(self.parse_expr()?);
1880        let span = lo.to(self.prev_token.span);
1881        self.psess.gated_spans.gate(sym::explicit_tail_calls, span);
1882        let expr = self.mk_expr(span, kind);
1883        self.maybe_recover_from_bad_qpath(expr)
1884    }
1885
1886    /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten.
1887    /// If the label is followed immediately by a `:` token, the label and `:` are
1888    /// parsed as part of the expression (i.e. a labeled loop). The language team has
1889    /// decided in #87026 to require parentheses as a visual aid to avoid confusion if
1890    /// the break expression of an unlabeled break is a labeled loop (as in
1891    /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
1892    /// expression only gets a warning for compatibility reasons; and a labeled break
1893    /// with a labeled loop does not even get a warning because there is no ambiguity.
1894    fn parse_expr_break(&mut self) -> PResult<'a, Box<Expr>> {
1895        let lo = self.prev_token.span;
1896        let mut label = self.eat_label();
1897        let kind = if self.token == token::Colon
1898            && let Some(label) = label.take()
1899        {
1900            // The value expression can be a labeled loop, see issue #86948, e.g.:
1901            // `loop { break 'label: loop { break 'label 42; }; }`
1902            let lexpr = self.parse_expr_labeled(label, true)?;
1903            self.dcx().emit_err(errors::LabeledLoopInBreak {
1904                span: lexpr.span,
1905                sub: errors::WrapInParentheses::Expression {
1906                    left: lexpr.span.shrink_to_lo(),
1907                    right: lexpr.span.shrink_to_hi(),
1908                },
1909            });
1910            Some(lexpr)
1911        } else if self.token != token::OpenBrace
1912            || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
1913        {
1914            let mut expr = self.parse_expr_opt()?;
1915            if let Some(expr) = &mut expr {
1916                if label.is_some()
1917                    && match &expr.kind {
1918                        ExprKind::While(_, _, None)
1919                        | ExprKind::ForLoop { label: None, .. }
1920                        | ExprKind::Loop(_, None, _) => true,
1921                        ExprKind::Block(block, None) => {
1922                            matches!(block.rules, BlockCheckMode::Default)
1923                        }
1924                        _ => false,
1925                    }
1926                {
1927                    self.psess.buffer_lint(
1928                        BREAK_WITH_LABEL_AND_LOOP,
1929                        lo.to(expr.span),
1930                        ast::CRATE_NODE_ID,
1931                        BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
1932                    );
1933                }
1934
1935                // Recover `break label aaaaa`
1936                if self.may_recover()
1937                    && let ExprKind::Path(None, p) = &expr.kind
1938                    && let [segment] = &*p.segments
1939                    && let &ast::PathSegment { ident, args: None, .. } = segment
1940                    && let Some(next) = self.parse_expr_opt()?
1941                {
1942                    label = Some(self.recover_ident_into_label(ident));
1943                    *expr = next;
1944                }
1945            }
1946
1947            expr
1948        } else {
1949            None
1950        };
1951        let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind));
1952        self.maybe_recover_from_bad_qpath(expr)
1953    }
1954
1955    /// Parse `"continue" label?`.
1956    fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
1957        let mut label = self.eat_label();
1958
1959        // Recover `continue label` -> `continue 'label`
1960        if self.may_recover()
1961            && label.is_none()
1962            && let Some((ident, _)) = self.token.ident()
1963        {
1964            self.bump();
1965            label = Some(self.recover_ident_into_label(ident));
1966        }
1967
1968        let kind = ExprKind::Continue(label);
1969        Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
1970    }
1971
1972    /// Parse `"yield" expr?`.
1973    fn parse_expr_yield(&mut self) -> PResult<'a, Box<Expr>> {
1974        let lo = self.prev_token.span;
1975        let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?));
1976        let span = lo.to(self.prev_token.span);
1977        self.psess.gated_spans.gate(sym::yield_expr, span);
1978        let expr = self.mk_expr(span, kind);
1979        self.maybe_recover_from_bad_qpath(expr)
1980    }
1981
1982    /// Parse `builtin # ident(args,*)`.
1983    fn parse_expr_builtin(&mut self) -> PResult<'a, Box<Expr>> {
1984        self.parse_builtin(|this, lo, ident| {
1985            Ok(match ident.name {
1986                sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
1987                sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?),
1988                sym::wrap_binder => {
1989                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?)
1990                }
1991                sym::unwrap_binder => {
1992                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?)
1993                }
1994                _ => None,
1995            })
1996        })
1997    }
1998
1999    pub(crate) fn parse_builtin<T>(
2000        &mut self,
2001        parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>,
2002    ) -> PResult<'a, T> {
2003        let lo = self.token.span;
2004
2005        self.bump(); // `builtin`
2006        self.bump(); // `#`
2007
2008        let Some((ident, IdentIsRaw::No)) = self.token.ident() else {
2009            let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span });
2010            return Err(err);
2011        };
2012        self.psess.gated_spans.gate(sym::builtin_syntax, ident.span);
2013        self.bump();
2014
2015        self.expect(exp!(OpenParen))?;
2016        let ret = if let Some(res) = parse(self, lo, ident)? {
2017            Ok(res)
2018        } else {
2019            let err = self.dcx().create_err(errors::UnknownBuiltinConstruct {
2020                span: lo.to(ident.span),
2021                name: ident,
2022            });
2023            return Err(err);
2024        };
2025        self.expect(exp!(CloseParen))?;
2026
2027        ret
2028    }
2029
2030    /// Built-in macro for `offset_of!` expressions.
2031    pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
2032        let container = self.parse_ty()?;
2033        self.expect(exp!(Comma))?;
2034
2035        let fields = self.parse_floating_field_access()?;
2036        let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
2037
2038        if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {
2039            if trailing_comma {
2040                e.note("unexpected third argument to offset_of");
2041            } else {
2042                e.note("offset_of expects dot-separated field and variant names");
2043            }
2044            e.emit();
2045        }
2046
2047        // Eat tokens until the macro call ends.
2048        if self.may_recover() {
2049            while !self.token.kind.is_close_delim_or_eof() {
2050                self.bump();
2051            }
2052        }
2053
2054        let span = lo.to(self.token.span);
2055        Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields)))
2056    }
2057
2058    /// Built-in macro for type ascription expressions.
2059    pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
2060        let expr = self.parse_expr()?;
2061        self.expect(exp!(Comma))?;
2062        let ty = self.parse_ty()?;
2063        let span = lo.to(self.token.span);
2064        Ok(self.mk_expr(span, ExprKind::Type(expr, ty)))
2065    }
2066
2067    pub(crate) fn parse_expr_unsafe_binder_cast(
2068        &mut self,
2069        lo: Span,
2070        kind: UnsafeBinderCastKind,
2071    ) -> PResult<'a, Box<Expr>> {
2072        let expr = self.parse_expr()?;
2073        let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None };
2074        let span = lo.to(self.token.span);
2075        Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty)))
2076    }
2077
2078    /// Returns a string literal if the next token is a string literal.
2079    /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
2080    /// and returns `None` if the next token is not literal at all.
2081    pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
2082        match self.parse_opt_meta_item_lit() {
2083            Some(lit) => match lit.kind {
2084                ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
2085                    style,
2086                    symbol: lit.symbol,
2087                    suffix: lit.suffix,
2088                    span: lit.span,
2089                    symbol_unescaped,
2090                }),
2091                _ => Err(Some(lit)),
2092            },
2093            None => Err(None),
2094        }
2095    }
2096
2097    pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
2098        (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
2099    }
2100
2101    fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
2102        ast::MetaItemLit {
2103            symbol: name,
2104            suffix: None,
2105            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
2106            span,
2107        }
2108    }
2109
2110    fn handle_missing_lit<L>(
2111        &mut self,
2112        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
2113    ) -> PResult<'a, L> {
2114        let token = self.token;
2115        let err = |self_: &Self| {
2116            let msg = format!("unexpected token: {}", super::token_descr(&token));
2117            self_.dcx().struct_span_err(token.span, msg)
2118        };
2119        // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
2120        // makes sense.
2121        if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
2122            && could_be_unclosed_char_literal(ident)
2123        {
2124            let lt = self.expect_lifetime();
2125            Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
2126        } else {
2127            Err(err(self))
2128        }
2129    }
2130
2131    pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
2132        self.parse_opt_token_lit()
2133            .ok_or(())
2134            .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
2135    }
2136
2137    pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
2138        self.parse_opt_meta_item_lit()
2139            .ok_or(())
2140            .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
2141    }
2142
2143    fn recover_after_dot(&mut self) {
2144        if self.token == token::Dot {
2145            // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
2146            // dot would follow an optional literal, so we do this unconditionally.
2147            let recovered = self.look_ahead(1, |next_token| {
2148                // If it's an integer that looks like a float, then recover as such.
2149                //
2150                // We will never encounter the exponent part of a floating
2151                // point literal here, since there's no use of the exponent
2152                // syntax that also constitutes a valid integer, so we need
2153                // not check for that.
2154                if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
2155                    next_token.kind
2156                    && suffix.is_none_or(|s| s == sym::f32 || s == sym::f64)
2157                    && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
2158                    && self.token.span.hi() == next_token.span.lo()
2159                {
2160                    let s = String::from("0.") + symbol.as_str();
2161                    let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
2162                    Some(Token::new(kind, self.token.span.to(next_token.span)))
2163                } else {
2164                    None
2165                }
2166            });
2167            if let Some(recovered) = recovered {
2168                self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart {
2169                    span: recovered.span,
2170                    suggestion: recovered.span.shrink_to_lo(),
2171                });
2172                self.bump();
2173                self.token = recovered;
2174            }
2175        }
2176    }
2177
2178    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
2179    /// `Lit::from_token` (excluding unary negation).
2180    pub fn eat_token_lit(&mut self) -> Option<token::Lit> {
2181        let check_expr = |expr: Box<Expr>| {
2182            if let ast::ExprKind::Lit(token_lit) = expr.kind {
2183                Some(token_lit)
2184            } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
2185                && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
2186            {
2187                None
2188            } else {
2189                panic!("unexpected reparsed expr/literal: {:?}", expr.kind);
2190            }
2191        };
2192        match self.token.uninterpolate().kind {
2193            token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => {
2194                self.bump();
2195                Some(token::Lit::new(token::Bool, name, None))
2196            }
2197            token::Literal(token_lit) => {
2198                self.bump();
2199                Some(token_lit)
2200            }
2201            token::OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Literal)) => {
2202                let lit = self
2203                    .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
2204                    .expect("metavar seq literal");
2205                check_expr(lit)
2206            }
2207            token::OpenInvisible(InvisibleOrigin::MetaVar(
2208                mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. },
2209            )) => {
2210                let expr = self
2211                    .eat_metavar_seq(mv_kind, |this| this.parse_expr())
2212                    .expect("metavar seq expr");
2213                check_expr(expr)
2214            }
2215            _ => None,
2216        }
2217    }
2218
2219    /// Matches `lit = true | false | token_lit`.
2220    /// Returns `None` if the next token is not a literal.
2221    fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
2222        self.recover_after_dot();
2223        let span = self.token.span;
2224        self.eat_token_lit().map(|token_lit| (token_lit, span))
2225    }
2226
2227    /// Matches `lit = true | false | token_lit`.
2228    /// Returns `None` if the next token is not a literal.
2229    fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
2230        self.recover_after_dot();
2231        let span = self.token.span;
2232        let uninterpolated_span = self.token_uninterpolated_span();
2233        self.eat_token_lit().map(|token_lit| {
2234            match MetaItemLit::from_token_lit(token_lit, span) {
2235                Ok(lit) => lit,
2236                Err(err) => {
2237                    let guar = report_lit_error(&self.psess, err, token_lit, uninterpolated_span);
2238                    // Pack possible quotes and prefixes from the original literal into
2239                    // the error literal's symbol so they can be pretty-printed faithfully.
2240                    let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
2241                    let symbol = Symbol::intern(&suffixless_lit.to_string());
2242                    let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
2243                    MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
2244                }
2245            }
2246        })
2247    }
2248
2249    /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
2250    /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
2251    pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> {
2252        if let Some(expr) = self.eat_metavar_seq_with_matcher(
2253            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
2254            |this| {
2255                // FIXME(nnethercote) The `expr` case should only match if
2256                // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
2257                // an `UnOp::Neg` and an `ExprKind::Lit`, like how
2258                // `can_begin_literal_maybe_minus` works. But this method has
2259                // been over-accepting for a long time, and to make that change
2260                // here requires also changing some `parse_literal_maybe_minus`
2261                // call sites to accept additional expression kinds. E.g.
2262                // `ExprKind::Path` must be accepted when parsing range
2263                // patterns. That requires some care. So for now, we continue
2264                // being less strict here than we should be.
2265                this.parse_expr()
2266            },
2267        ) {
2268            return Ok(expr);
2269        } else if let Some(lit) =
2270            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
2271        {
2272            return Ok(lit);
2273        }
2274
2275        let lo = self.token.span;
2276        let minus_present = self.eat(exp!(Minus));
2277        let (token_lit, span) = self.parse_token_lit()?;
2278        let expr = self.mk_expr(span, ExprKind::Lit(token_lit));
2279
2280        if minus_present {
2281            Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
2282        } else {
2283            Ok(expr)
2284        }
2285    }
2286
2287    fn is_array_like_block(&mut self) -> bool {
2288        self.token.kind == TokenKind::OpenBrace
2289            && self
2290                .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
2291            && self.look_ahead(2, |t| t == &token::Comma)
2292            && self.look_ahead(3, |t| t.can_begin_expr())
2293    }
2294
2295    /// Emits a suggestion if it looks like the user meant an array but
2296    /// accidentally used braces, causing the code to be interpreted as a block
2297    /// expression.
2298    fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<Box<Expr>> {
2299        let mut snapshot = self.create_snapshot_for_diagnostic();
2300        match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
2301            Ok(arr) => {
2302                let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
2303                    span: arr.span,
2304                    sub: errors::ArrayBracketsInsteadOfBracesSugg {
2305                        left: lo,
2306                        right: snapshot.prev_token.span,
2307                    },
2308                });
2309
2310                self.restore_snapshot(snapshot);
2311                Some(self.mk_expr_err(arr.span, guar))
2312            }
2313            Err(e) => {
2314                e.cancel();
2315                None
2316            }
2317        }
2318    }
2319
2320    fn suggest_missing_semicolon_before_array(
2321        &self,
2322        prev_span: Span,
2323        open_delim_span: Span,
2324    ) -> PResult<'a, ()> {
2325        if !self.may_recover() {
2326            return Ok(());
2327        }
2328
2329        if self.token == token::Comma {
2330            if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) {
2331                return Ok(());
2332            }
2333            let mut snapshot = self.create_snapshot_for_diagnostic();
2334            snapshot.bump();
2335            match snapshot.parse_seq_to_before_end(
2336                exp!(CloseBracket),
2337                SeqSep::trailing_allowed(exp!(Comma)),
2338                |p| p.parse_expr(),
2339            ) {
2340                Ok(_)
2341                    // When the close delim is `)`, `token.kind` is expected to be `token::CloseParen`,
2342                    // but the actual `token.kind` is `token::CloseBracket`.
2343                    // This is because the `token.kind` of the close delim is treated as the same as
2344                    // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
2345                    // Therefore, `token.kind` should not be compared here.
2346                    if snapshot
2347                        .span_to_snippet(snapshot.token.span)
2348                        .is_ok_and(|snippet| snippet == "]") =>
2349                {
2350                    return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray {
2351                        open_delim: open_delim_span,
2352                        semicolon: prev_span.shrink_to_hi(),
2353                    }));
2354                }
2355                Ok(_) => (),
2356                Err(err) => err.cancel(),
2357            }
2358        }
2359        Ok(())
2360    }
2361
2362    /// Parses a block or unsafe block.
2363    pub(super) fn parse_expr_block(
2364        &mut self,
2365        opt_label: Option<Label>,
2366        lo: Span,
2367        blk_mode: BlockCheckMode,
2368    ) -> PResult<'a, Box<Expr>> {
2369        if self.may_recover() && self.is_array_like_block() {
2370            if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
2371                return Ok(arr);
2372            }
2373        }
2374
2375        if self.token.is_metavar_block() {
2376            self.dcx().emit_err(errors::InvalidBlockMacroSegment {
2377                span: self.token.span,
2378                context: lo.to(self.token.span),
2379                wrap: errors::WrapInExplicitBlock {
2380                    lo: self.token.span.shrink_to_lo(),
2381                    hi: self.token.span.shrink_to_hi(),
2382                },
2383            });
2384        }
2385
2386        let (attrs, blk) = self.parse_block_common(lo, blk_mode, None)?;
2387        Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
2388    }
2389
2390    /// Parse a block which takes no attributes and has no label
2391    fn parse_simple_block(&mut self) -> PResult<'a, Box<Expr>> {
2392        let blk = self.parse_block()?;
2393        Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
2394    }
2395
2396    /// Parses a closure expression (e.g., `move |args| expr`).
2397    fn parse_expr_closure(&mut self) -> PResult<'a, Box<Expr>> {
2398        let lo = self.token.span;
2399
2400        let before = self.prev_token;
2401        let binder = if self.check_keyword(exp!(For)) {
2402            let lo = self.token.span;
2403            let (bound_vars, _) = self.parse_higher_ranked_binder()?;
2404            let span = lo.to(self.prev_token.span);
2405
2406            self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);
2407
2408            ClosureBinder::For { span, generic_params: bound_vars }
2409        } else {
2410            ClosureBinder::NotPresent
2411        };
2412
2413        let constness = self.parse_closure_constness();
2414
2415        let movability = if self.eat_keyword(exp!(Static)) {
2416            self.psess.gated_spans.gate(sym::coroutines, self.prev_token.span);
2417            Movability::Static
2418        } else {
2419            Movability::Movable
2420        };
2421
2422        let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() {
2423            self.parse_coroutine_kind(Case::Sensitive)
2424        } else {
2425            None
2426        };
2427
2428        if let ClosureBinder::NotPresent = binder
2429            && coroutine_kind.is_some()
2430        {
2431            // coroutine closures and generators can have the same qualifiers, so we might end up
2432            // in here if there is a missing `|` but also no `{`. Adjust the expectations in that case.
2433            self.expected_token_types.insert(TokenType::OpenBrace);
2434        }
2435
2436        let capture_clause = self.parse_capture_clause()?;
2437        let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
2438        let decl_hi = self.prev_token.span;
2439        let mut body = match &fn_decl.output {
2440            // No return type.
2441            FnRetTy::Default(_) => {
2442                let restrictions =
2443                    self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
2444                let prev = self.prev_token;
2445                let token = self.token;
2446                let attrs = self.parse_outer_attributes()?;
2447                match self.parse_expr_res(restrictions, attrs) {
2448                    Ok((expr, _)) => expr,
2449                    Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
2450                }
2451            }
2452            // Explicit return type (`->`) needs block `-> T { }`.
2453            FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
2454        };
2455
2456        match coroutine_kind {
2457            Some(CoroutineKind::Async { .. }) => {}
2458            Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
2459                // Feature-gate `gen ||` and `async gen ||` closures.
2460                // FIXME(gen_blocks): This perhaps should be a different gate.
2461                self.psess.gated_spans.gate(sym::gen_blocks, span);
2462            }
2463            None => {}
2464        }
2465
2466        if self.token == TokenKind::Semi
2467            && let Some(last) = self.token_cursor.stack.last()
2468            && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = last.curr()
2469            && self.may_recover()
2470        {
2471            // It is likely that the closure body is a block but where the
2472            // braces have been removed. We will recover and eat the next
2473            // statements later in the parsing process.
2474            body = self.mk_expr_err(
2475                body.span,
2476                self.dcx().span_delayed_bug(body.span, "recovered a closure body as a block"),
2477            );
2478        }
2479
2480        let body_span = body.span;
2481
2482        let closure = self.mk_expr(
2483            lo.to(body.span),
2484            ExprKind::Closure(Box::new(ast::Closure {
2485                binder,
2486                capture_clause,
2487                constness,
2488                coroutine_kind,
2489                movability,
2490                fn_decl,
2491                body,
2492                fn_decl_span: lo.to(decl_hi),
2493                fn_arg_span,
2494            })),
2495        );
2496
2497        // Disable recovery for closure body
2498        let spans =
2499            ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
2500        self.current_closure = Some(spans);
2501
2502        Ok(closure)
2503    }
2504
2505    /// If an explicit return type is given, require a block to appear (RFC 968).
2506    fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, Box<Expr>> {
2507        if self.may_recover()
2508            && self.token.can_begin_expr()
2509            && self.token.kind != TokenKind::OpenBrace
2510            && !self.token.is_metavar_block()
2511        {
2512            let snapshot = self.create_snapshot_for_diagnostic();
2513            let restrictions =
2514                self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
2515            let tok = self.token.clone();
2516            match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
2517                Ok((expr, _)) => {
2518                    let descr = super::token_descr(&tok);
2519                    let mut diag = self
2520                        .dcx()
2521                        .struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
2522                    diag.span_label(
2523                        ret_span,
2524                        "explicit return type requires closure body to be enclosed in braces",
2525                    );
2526                    diag.multipart_suggestion_verbose(
2527                        "wrap the expression in curly braces",
2528                        vec![
2529                            (expr.span.shrink_to_lo(), "{ ".to_string()),
2530                            (expr.span.shrink_to_hi(), " }".to_string()),
2531                        ],
2532                        Applicability::MachineApplicable,
2533                    );
2534                    diag.emit();
2535                    return Ok(expr);
2536                }
2537                Err(diag) => {
2538                    diag.cancel();
2539                    self.restore_snapshot(snapshot);
2540                }
2541            }
2542        }
2543
2544        let body_lo = self.token.span;
2545        self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
2546    }
2547
2548    /// Parses an optional `move` or `use` prefix to a closure-like construct.
2549    fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
2550        if self.eat_keyword(exp!(Move)) {
2551            let move_kw_span = self.prev_token.span;
2552            // Check for `move async` and recover
2553            if self.check_keyword(exp!(Async)) {
2554                let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2555                Err(self
2556                    .dcx()
2557                    .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span }))
2558            } else {
2559                Ok(CaptureBy::Value { move_kw: move_kw_span })
2560            }
2561        } else if self.eat_keyword(exp!(Use)) {
2562            let use_kw_span = self.prev_token.span;
2563            self.psess.gated_spans.gate(sym::ergonomic_clones, use_kw_span);
2564            // Check for `use async` and recover
2565            if self.check_keyword(exp!(Async)) {
2566                let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
2567                Err(self.dcx().create_err(errors::AsyncUseOrderIncorrect { span: use_async_span }))
2568            } else {
2569                Ok(CaptureBy::Use { use_kw: use_kw_span })
2570            }
2571        } else {
2572            Ok(CaptureBy::Ref)
2573        }
2574    }
2575
2576    /// Parses the `|arg, arg|` header of a closure.
2577    fn parse_fn_block_decl(&mut self) -> PResult<'a, (Box<FnDecl>, Span)> {
2578        let arg_start = self.token.span.lo();
2579
2580        let inputs = if self.eat(exp!(OrOr)) {
2581            ThinVec::new()
2582        } else {
2583            self.expect(exp!(Or))?;
2584            let args = self
2585                .parse_seq_to_before_tokens(
2586                    &[exp!(Or)],
2587                    &[&token::OrOr],
2588                    SeqSep::trailing_allowed(exp!(Comma)),
2589                    |p| p.parse_fn_block_param(),
2590                )?
2591                .0;
2592            self.expect_or()?;
2593            args
2594        };
2595        let arg_span = self.prev_token.span.with_lo(arg_start);
2596        let output =
2597            self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?;
2598
2599        Ok((Box::new(FnDecl { inputs, output }), arg_span))
2600    }
2601
2602    /// Parses a parameter in a closure header (e.g., `|arg, arg|`).
2603    fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
2604        let lo = self.token.span;
2605        let attrs = self.parse_outer_attributes()?;
2606        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
2607            let pat = Box::new(this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?);
2608            let ty = if this.eat(exp!(Colon)) {
2609                this.parse_ty()?
2610            } else {
2611                this.mk_ty(pat.span, TyKind::Infer)
2612            };
2613
2614            Ok((
2615                Param {
2616                    attrs,
2617                    ty,
2618                    pat,
2619                    span: lo.to(this.prev_token.span),
2620                    id: DUMMY_NODE_ID,
2621                    is_placeholder: false,
2622                },
2623                Trailing::from(this.token == token::Comma),
2624                UsePreAttrPos::No,
2625            ))
2626        })
2627    }
2628
2629    /// Parses an `if` expression (`if` token already eaten).
2630    fn parse_expr_if(&mut self) -> PResult<'a, Box<Expr>> {
2631        let lo = self.prev_token.span;
2632        // Scoping code checks the top level edition of the `if`; let's match it here.
2633        // The `CondChecker` also checks the edition of the `let` itself, just to make sure.
2634        let let_chains_policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
2635        let cond = self.parse_expr_cond(let_chains_policy)?;
2636        self.parse_if_after_cond(lo, cond)
2637    }
2638
2639    fn parse_if_after_cond(&mut self, lo: Span, mut cond: Box<Expr>) -> PResult<'a, Box<Expr>> {
2640        let cond_span = cond.span;
2641        // Tries to interpret `cond` as either a missing expression if it's a block,
2642        // or as an unfinished expression if it's a binop and the RHS is a block.
2643        // We could probably add more recoveries here too...
2644        let mut recover_block_from_condition = |this: &mut Self| {
2645            let block = match &mut cond.kind {
2646                ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
2647                    if let ExprKind::Block(_, None) = right.kind =>
2648                {
2649                    let guar = this.dcx().emit_err(errors::IfExpressionMissingThenBlock {
2650                        if_span: lo,
2651                        missing_then_block_sub:
2652                            errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(
2653                                cond_span.shrink_to_lo().to(*binop_span),
2654                            ),
2655                        let_else_sub: None,
2656                    });
2657                    std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi(), guar))
2658                }
2659                ExprKind::Block(_, None) => {
2660                    let guar = this.dcx().emit_err(errors::IfExpressionMissingCondition {
2661                        if_span: lo.with_neighbor(cond.span).shrink_to_hi(),
2662                        block_span: self.psess.source_map().start_point(cond_span),
2663                    });
2664                    std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar))
2665                }
2666                _ => {
2667                    return None;
2668                }
2669            };
2670            if let ExprKind::Block(block, _) = &block.kind {
2671                Some(block.clone())
2672            } else {
2673                unreachable!()
2674            }
2675        };
2676        // Parse then block
2677        let thn = if self.token.is_keyword(kw::Else) {
2678            if let Some(block) = recover_block_from_condition(self) {
2679                block
2680            } else {
2681                let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
2682                    .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
2683
2684                let guar = self.dcx().emit_err(errors::IfExpressionMissingThenBlock {
2685                    if_span: lo,
2686                    missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
2687                        cond_span.shrink_to_hi(),
2688                    ),
2689                    let_else_sub,
2690                });
2691                self.mk_block_err(cond_span.shrink_to_hi(), guar)
2692            }
2693        } else {
2694            let attrs = self.parse_outer_attributes()?; // For recovery.
2695            let maybe_fatarrow = self.token;
2696            let block = if self.check(exp!(OpenBrace)) {
2697                self.parse_block()?
2698            } else if let Some(block) = recover_block_from_condition(self) {
2699                block
2700            } else {
2701                self.error_on_extra_if(&cond)?;
2702                // Parse block, which will always fail, but we can add a nice note to the error
2703                self.parse_block().map_err(|mut err| {
2704                        if self.prev_token == token::Semi
2705                            && self.token == token::AndAnd
2706                            && let maybe_let = self.look_ahead(1, |t| t.clone())
2707                            && maybe_let.is_keyword(kw::Let)
2708                        {
2709                            err.span_suggestion(
2710                                self.prev_token.span,
2711                                "consider removing this semicolon to parse the `let` as part of the same chain",
2712                                "",
2713                                Applicability::MachineApplicable,
2714                            ).span_note(
2715                                self.token.span.to(maybe_let.span),
2716                                "you likely meant to continue parsing the let-chain starting here",
2717                            );
2718                        } else {
2719                            // Look for usages of '=>' where '>=' might be intended
2720                            if maybe_fatarrow == token::FatArrow {
2721                                err.span_suggestion(
2722                                    maybe_fatarrow.span,
2723                                    "you might have meant to write a \"greater than or equal to\" comparison",
2724                                    ">=",
2725                                    Applicability::MaybeIncorrect,
2726                                );
2727                            }
2728                            err.span_note(
2729                                cond_span,
2730                                "the `if` expression is missing a block after this condition",
2731                            );
2732                        }
2733                        err
2734                    })?
2735            };
2736            self.error_on_if_block_attrs(lo, false, block.span, attrs);
2737            block
2738        };
2739        let els = if self.eat_keyword(exp!(Else)) { Some(self.parse_expr_else()?) } else { None };
2740        Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
2741    }
2742
2743    /// Parses the condition of a `if` or `while` expression.
2744    ///
2745    /// The specified `edition` in `let_chains_policy` should be that of the whole `if` construct,
2746    /// i.e. the same span we use to later decide whether the drop behaviour should be that of
2747    /// edition `..=2021` or that of `2024..`.
2748    // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt
2749    pub fn parse_expr_cond(
2750        &mut self,
2751        let_chains_policy: LetChainsPolicy,
2752    ) -> PResult<'a, Box<Expr>> {
2753        let attrs = self.parse_outer_attributes()?;
2754        let (mut cond, _) =
2755            self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;
2756
2757        CondChecker::new(self, let_chains_policy).visit_expr(&mut cond);
2758
2759        Ok(cond)
2760    }
2761
2762    /// Parses a `let $pat = $expr` pseudo-expression.
2763    fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
2764        let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
2765            let err = errors::ExpectedExpressionFoundLet {
2766                span: self.token.span,
2767                reason: ForbiddenLetReason::OtherForbidden,
2768                missing_let: None,
2769                comparison: None,
2770            };
2771            if self.prev_token == token::Or {
2772                // This was part of a closure, the that part of the parser recover.
2773                return Err(self.dcx().create_err(err));
2774            } else {
2775                Recovered::Yes(self.dcx().emit_err(err))
2776            }
2777        } else {
2778            Recovered::No
2779        };
2780        self.bump(); // Eat `let` token
2781        let lo = self.prev_token.span;
2782        let pat = self.parse_pat_no_top_guard(
2783            None,
2784            RecoverComma::Yes,
2785            RecoverColon::Yes,
2786            CommaRecoveryMode::LikelyTuple,
2787        )?;
2788        if self.token == token::EqEq {
2789            self.dcx().emit_err(errors::ExpectedEqForLetExpr {
2790                span: self.token.span,
2791                sugg_span: self.token.span,
2792            });
2793            self.bump();
2794        } else {
2795            self.expect(exp!(Eq))?;
2796        }
2797        let attrs = self.parse_outer_attributes()?;
2798        let (expr, _) =
2799            self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?;
2800        let span = lo.to(expr.span);
2801        Ok(self.mk_expr(span, ExprKind::Let(Box::new(pat), expr, span, recovered)))
2802    }
2803
2804    /// Parses an `else { ... }` expression (`else` token already eaten).
2805    fn parse_expr_else(&mut self) -> PResult<'a, Box<Expr>> {
2806        let else_span = self.prev_token.span; // `else`
2807        let attrs = self.parse_outer_attributes()?; // For recovery.
2808        let expr = if self.eat_keyword(exp!(If)) {
2809            ensure_sufficient_stack(|| self.parse_expr_if())?
2810        } else if self.check(exp!(OpenBrace)) {
2811            self.parse_simple_block()?
2812        } else {
2813            let snapshot = self.create_snapshot_for_diagnostic();
2814            let first_tok = super::token_descr(&self.token);
2815            let first_tok_span = self.token.span;
2816            match self.parse_expr() {
2817                Ok(cond)
2818                // Try to guess the difference between a "condition-like" vs
2819                // "statement-like" expression.
2820                //
2821                // We are seeing the following code, in which $cond is neither
2822                // ExprKind::Block nor ExprKind::If (the 2 cases wherein this
2823                // would be valid syntax).
2824                //
2825                //     if ... {
2826                //     } else $cond
2827                //
2828                // If $cond is "condition-like" such as ExprKind::Binary, we
2829                // want to suggest inserting `if`.
2830                //
2831                //     if ... {
2832                //     } else if a == b {
2833                //            ^^
2834                //     }
2835                //
2836                // We account for macro calls that were meant as conditions as well.
2837                //
2838                //     if ... {
2839                //     } else if macro! { foo bar } {
2840                //            ^^
2841                //     }
2842                //
2843                // If $cond is "statement-like" such as ExprKind::While then we
2844                // want to suggest wrapping in braces.
2845                //
2846                //     if ... {
2847                //     } else {
2848                //            ^
2849                //         while true {}
2850                //     }
2851                //     ^
2852                    if self.check(exp!(OpenBrace))
2853                        && (classify::expr_requires_semi_to_be_stmt(&cond)
2854                            || matches!(cond.kind, ExprKind::MacCall(..)))
2855                    =>
2856                {
2857                    self.dcx().emit_err(errors::ExpectedElseBlock {
2858                        first_tok_span,
2859                        first_tok,
2860                        else_span,
2861                        condition_start: cond.span.shrink_to_lo(),
2862                    });
2863                    self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
2864                }
2865                Err(e) => {
2866                    e.cancel();
2867                    self.restore_snapshot(snapshot);
2868                    self.parse_simple_block()?
2869                },
2870                Ok(_) => {
2871                    self.restore_snapshot(snapshot);
2872                    self.parse_simple_block()?
2873                },
2874            }
2875        };
2876        self.error_on_if_block_attrs(else_span, true, expr.span, attrs);
2877        Ok(expr)
2878    }
2879
2880    fn error_on_if_block_attrs(
2881        &self,
2882        ctx_span: Span,
2883        is_ctx_else: bool,
2884        branch_span: Span,
2885        attrs: AttrWrapper,
2886    ) {
2887        if !attrs.is_empty()
2888            && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess)
2889        {
2890            let attributes = x0.span.until(branch_span);
2891            let last = xn.span;
2892            let ctx = if is_ctx_else { "else" } else { "if" };
2893            self.dcx().emit_err(errors::OuterAttributeNotAllowedOnIfElse {
2894                last,
2895                branch_span,
2896                ctx_span,
2897                ctx: ctx.to_string(),
2898                attributes,
2899            });
2900        }
2901    }
2902
2903    fn error_on_extra_if(&mut self, cond: &Box<Expr>) -> PResult<'a, ()> {
2904        if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind
2905            && let BinOpKind::And = binop
2906            && let ExprKind::If(cond, ..) = &right.kind
2907        {
2908            Err(self.dcx().create_err(errors::UnexpectedIfWithIf(
2909                binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()),
2910            )))
2911        } else {
2912            Ok(())
2913        }
2914    }
2915
2916    // Public to use it for custom `for` expressions in rustfmt forks like https://github.com/tucant/rustfmt
2917    pub fn parse_for_head(&mut self) -> PResult<'a, (Pat, Box<Expr>)> {
2918        let begin_paren = if self.token == token::OpenParen {
2919            // Record whether we are about to parse `for (`.
2920            // This is used below for recovery in case of `for ( $stuff ) $block`
2921            // in which case we will suggest `for $stuff $block`.
2922            let start_span = self.token.span;
2923            let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
2924            Some((start_span, left))
2925        } else {
2926            None
2927        };
2928        // Try to parse the pattern `for ($PAT) in $EXPR`.
2929        let pat = match (
2930            self.parse_pat_allow_top_guard(
2931                None,
2932                RecoverComma::Yes,
2933                RecoverColon::Yes,
2934                CommaRecoveryMode::LikelyTuple,
2935            ),
2936            begin_paren,
2937        ) {
2938            (Ok(pat), _) => pat, // Happy path.
2939            (Err(err), Some((start_span, left))) if self.eat_keyword(exp!(In)) => {
2940                // We know for sure we have seen `for ($SOMETHING in`. In the happy path this would
2941                // happen right before the return of this method.
2942                let attrs = self.parse_outer_attributes()?;
2943                let (expr, _) = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs) {
2944                    Ok(expr) => expr,
2945                    Err(expr_err) => {
2946                        // We don't know what followed the `in`, so cancel and bubble up the
2947                        // original error.
2948                        expr_err.cancel();
2949                        return Err(err);
2950                    }
2951                };
2952                return if self.token == token::CloseParen {
2953                    // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
2954                    // parser state and emit a targeted suggestion.
2955                    let span = vec![start_span, self.token.span];
2956                    let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
2957                    self.bump(); // )
2958                    err.cancel();
2959                    self.dcx().emit_err(errors::ParenthesesInForHead {
2960                        span,
2961                        // With e.g. `for (x) in y)` this would replace `(x) in y)`
2962                        // with `x) in y)` which is syntactically invalid.
2963                        // However, this is prevented before we get here.
2964                        sugg: errors::ParenthesesInForHeadSugg { left, right },
2965                    });
2966                    Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr))
2967                } else {
2968                    Err(err) // Some other error, bubble up.
2969                };
2970            }
2971            (Err(err), _) => return Err(err), // Some other error, bubble up.
2972        };
2973        if !self.eat_keyword(exp!(In)) {
2974            self.error_missing_in_for_loop();
2975        }
2976        self.check_for_for_in_in_typo(self.prev_token.span);
2977        let attrs = self.parse_outer_attributes()?;
2978        let (expr, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
2979        Ok((pat, expr))
2980    }
2981
2982    /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
2983    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
2984        let is_await =
2985            self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));
2986
2987        if is_await {
2988            self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
2989        }
2990
2991        let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For };
2992
2993        let (pat, expr) = self.parse_for_head()?;
2994        let pat = Box::new(pat);
2995        // Recover from missing expression in `for` loop
2996        if matches!(expr.kind, ExprKind::Block(..))
2997            && self.token.kind != token::OpenBrace
2998            && self.may_recover()
2999        {
3000            let guar = self
3001                .dcx()
3002                .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
3003            let err_expr = self.mk_expr(expr.span, ExprKind::Err(guar));
3004            let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span);
3005            return Ok(self.mk_expr(
3006                lo.to(self.prev_token.span),
3007                ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, kind },
3008            ));
3009        }
3010
3011        let (attrs, loop_block) = self.parse_inner_attrs_and_block(
3012            // Only suggest moving erroneous block label to the loop header
3013            // if there is not already a label there
3014            opt_label.is_none().then_some(lo),
3015        )?;
3016
3017        let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind };
3018
3019        self.recover_loop_else("for", lo)?;
3020
3021        Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
3022    }
3023
3024    /// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
3025    fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
3026        if self.token.is_keyword(kw::Else) && self.may_recover() {
3027            let else_span = self.token.span;
3028            self.bump();
3029            let else_clause = self.parse_expr_else()?;
3030            self.dcx().emit_err(errors::LoopElseNotSupported {
3031                span: else_span.to(else_clause.span),
3032                loop_kind,
3033                loop_kw,
3034            });
3035        }
3036        Ok(())
3037    }
3038
3039    fn error_missing_in_for_loop(&mut self) {
3040        let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
3041            // Possibly using JS syntax (#75311).
3042            let span = self.token.span;
3043            self.bump();
3044            (span, errors::MissingInInForLoopSub::InNotOf)
3045        } else if self.eat(exp!(Eq)) {
3046            (self.prev_token.span, errors::MissingInInForLoopSub::InNotEq)
3047        } else {
3048            (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
3049        };
3050
3051        self.dcx().emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
3052    }
3053
3054    /// Parses a `while` or `while let` expression (`while` token already eaten).
3055    fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
3056        let policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
3057        let cond = self.parse_expr_cond(policy).map_err(|mut err| {
3058            err.span_label(lo, "while parsing the condition of this `while` expression");
3059            err
3060        })?;
3061        let (attrs, body) = self
3062            .parse_inner_attrs_and_block(
3063                // Only suggest moving erroneous block label to the loop header
3064                // if there is not already a label there
3065                opt_label.is_none().then_some(lo),
3066            )
3067            .map_err(|mut err| {
3068                err.span_label(lo, "while parsing the body of this `while` expression");
3069                err.span_label(cond.span, "this `while` condition successfully parsed");
3070                err
3071            })?;
3072
3073        self.recover_loop_else("while", lo)?;
3074
3075        Ok(self.mk_expr_with_attrs(
3076            lo.to(self.prev_token.span),
3077            ExprKind::While(cond, body, opt_label),
3078            attrs,
3079        ))
3080    }
3081
3082    /// Parses `loop { ... }` (`loop` token already eaten).
3083    fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
3084        let loop_span = self.prev_token.span;
3085        let (attrs, body) = self.parse_inner_attrs_and_block(
3086            // Only suggest moving erroneous block label to the loop header
3087            // if there is not already a label there
3088            opt_label.is_none().then_some(lo),
3089        )?;
3090        self.recover_loop_else("loop", lo)?;
3091        Ok(self.mk_expr_with_attrs(
3092            lo.to(self.prev_token.span),
3093            ExprKind::Loop(body, opt_label, loop_span),
3094            attrs,
3095        ))
3096    }
3097
3098    pub(crate) fn eat_label(&mut self) -> Option<Label> {
3099        if let Some((ident, is_raw)) = self.token.lifetime() {
3100            // Disallow `'fn`, but with a better error message than `expect_lifetime`.
3101            if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved() {
3102                self.dcx().emit_err(errors::KeywordLabel { span: ident.span });
3103            }
3104
3105            self.bump();
3106            Some(Label { ident })
3107        } else {
3108            None
3109        }
3110    }
3111
3112    /// Parses a `match ... { ... }` expression (`match` token already eaten).
3113    fn parse_expr_match(&mut self) -> PResult<'a, Box<Expr>> {
3114        let match_span = self.prev_token.span;
3115        let attrs = self.parse_outer_attributes()?;
3116        let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
3117
3118        self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix)
3119    }
3120
3121    /// Parses the block of a `match expr { ... }` or a `expr.match { ... }`
3122    /// expression. This is after the match token and scrutinee are eaten
3123    fn parse_match_block(
3124        &mut self,
3125        lo: Span,
3126        match_span: Span,
3127        scrutinee: Box<Expr>,
3128        match_kind: MatchKind,
3129    ) -> PResult<'a, Box<Expr>> {
3130        if let Err(mut e) = self.expect(exp!(OpenBrace)) {
3131            if self.token == token::Semi {
3132                e.span_suggestion_short(
3133                    match_span,
3134                    "try removing this `match`",
3135                    "",
3136                    Applicability::MaybeIncorrect, // speculative
3137                );
3138            }
3139            if self.maybe_recover_unexpected_block_label(None) {
3140                e.cancel();
3141                self.bump();
3142            } else {
3143                return Err(e);
3144            }
3145        }
3146        let attrs = self.parse_inner_attributes()?;
3147
3148        let mut arms = ThinVec::new();
3149        while self.token != token::CloseBrace {
3150            match self.parse_arm() {
3151                Ok(arm) => arms.push(arm),
3152                Err(e) => {
3153                    // Recover by skipping to the end of the block.
3154                    let guar = e.emit();
3155                    self.recover_stmt();
3156                    let span = lo.to(self.token.span);
3157                    if self.token == token::CloseBrace {
3158                        self.bump();
3159                    }
3160                    // Always push at least one arm to make the match non-empty
3161                    arms.push(Arm {
3162                        attrs: Default::default(),
3163                        pat: Box::new(self.mk_pat(span, ast::PatKind::Err(guar))),
3164                        guard: None,
3165                        body: Some(self.mk_expr_err(span, guar)),
3166                        span,
3167                        id: DUMMY_NODE_ID,
3168                        is_placeholder: false,
3169                    });
3170                    return Ok(self.mk_expr_with_attrs(
3171                        span,
3172                        ExprKind::Match(scrutinee, arms, match_kind),
3173                        attrs,
3174                    ));
3175                }
3176            }
3177        }
3178        let hi = self.token.span;
3179        self.bump();
3180        Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs))
3181    }
3182
3183    /// Attempt to recover from match arm body with statements and no surrounding braces.
3184    fn parse_arm_body_missing_braces(
3185        &mut self,
3186        first_expr: &Box<Expr>,
3187        arrow_span: Span,
3188    ) -> Option<(Span, ErrorGuaranteed)> {
3189        if self.token != token::Semi {
3190            return None;
3191        }
3192        let start_snapshot = self.create_snapshot_for_diagnostic();
3193        let semi_sp = self.token.span;
3194        self.bump(); // `;`
3195        let mut stmts =
3196            vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
3197        let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
3198            let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
3199
3200            let guar = this.dcx().emit_err(errors::MatchArmBodyWithoutBraces {
3201                statements: span,
3202                arrow: arrow_span,
3203                num_statements: stmts.len(),
3204                sub: if stmts.len() > 1 {
3205                    errors::MatchArmBodyWithoutBracesSugg::AddBraces {
3206                        left: span.shrink_to_lo(),
3207                        right: span.shrink_to_hi(),
3208                    }
3209                } else {
3210                    errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
3211                },
3212            });
3213            (span, guar)
3214        };
3215        // We might have either a `,` -> `;` typo, or a block without braces. We need
3216        // a more subtle parsing strategy.
3217        loop {
3218            if self.token == token::CloseBrace {
3219                // We have reached the closing brace of the `match` expression.
3220                return Some(err(self, stmts));
3221            }
3222            if self.token == token::Comma {
3223                self.restore_snapshot(start_snapshot);
3224                return None;
3225            }
3226            let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
3227            match self.parse_pat_no_top_alt(None, None) {
3228                Ok(_pat) => {
3229                    if self.token == token::FatArrow {
3230                        // Reached arm end.
3231                        self.restore_snapshot(pre_pat_snapshot);
3232                        return Some(err(self, stmts));
3233                    }
3234                }
3235                Err(err) => {
3236                    err.cancel();
3237                }
3238            }
3239
3240            self.restore_snapshot(pre_pat_snapshot);
3241            match self.parse_stmt_without_recovery(true, ForceCollect::No, false) {
3242                // Consume statements for as long as possible.
3243                Ok(Some(stmt)) => {
3244                    stmts.push(stmt);
3245                }
3246                Ok(None) => {
3247                    self.restore_snapshot(start_snapshot);
3248                    break;
3249                }
3250                // We couldn't parse either yet another statement missing it's
3251                // enclosing block nor the next arm's pattern or closing brace.
3252                Err(stmt_err) => {
3253                    stmt_err.cancel();
3254                    self.restore_snapshot(start_snapshot);
3255                    break;
3256                }
3257            }
3258        }
3259        None
3260    }
3261
3262    pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
3263        let attrs = self.parse_outer_attributes()?;
3264        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3265            let lo = this.token.span;
3266            let (pat, guard) = this.parse_match_arm_pat_and_guard()?;
3267            let pat = Box::new(pat);
3268
3269            let span_before_body = this.prev_token.span;
3270            let arm_body;
3271            let is_fat_arrow = this.check(exp!(FatArrow));
3272            let is_almost_fat_arrow =
3273                TokenKind::FatArrow.similar_tokens().contains(&this.token.kind);
3274
3275            // this avoids the compiler saying that a `,` or `}` was expected even though
3276            // the pattern isn't a never pattern (and thus an arm body is required)
3277            let armless = (!is_fat_arrow && !is_almost_fat_arrow && pat.could_be_never_pattern())
3278                || matches!(this.token.kind, token::Comma | token::CloseBrace);
3279
3280            let mut result = if armless {
3281                // A pattern without a body, allowed for never patterns.
3282                arm_body = None;
3283                let span = lo.to(this.prev_token.span);
3284                this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map(|x| {
3285                    // Don't gate twice
3286                    if !pat.contains_never_pattern() {
3287                        this.psess.gated_spans.gate(sym::never_patterns, span);
3288                    }
3289                    x
3290                })
3291            } else {
3292                if let Err(mut err) = this.expect(exp!(FatArrow)) {
3293                    // We might have a `=>` -> `=` or `->` typo (issue #89396).
3294                    if is_almost_fat_arrow {
3295                        err.span_suggestion(
3296                            this.token.span,
3297                            "use a fat arrow to start a match arm",
3298                            "=>",
3299                            Applicability::MachineApplicable,
3300                        );
3301                        if matches!(
3302                            (&this.prev_token.kind, &this.token.kind),
3303                            (token::DotDotEq, token::Gt)
3304                        ) {
3305                            // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
3306                            // so we suppress the error here
3307                            err.delay_as_bug();
3308                        } else {
3309                            err.emit();
3310                        }
3311                        this.bump();
3312                    } else {
3313                        return Err(err);
3314                    }
3315                }
3316                let arrow_span = this.prev_token.span;
3317                let arm_start_span = this.token.span;
3318
3319                let attrs = this.parse_outer_attributes()?;
3320                let (expr, _) =
3321                    this.parse_expr_res(Restrictions::STMT_EXPR, attrs).map_err(|mut err| {
3322                        err.span_label(arrow_span, "while parsing the `match` arm starting here");
3323                        err
3324                    })?;
3325
3326                let require_comma =
3327                    !classify::expr_is_complete(&expr) && this.token != token::CloseBrace;
3328
3329                if !require_comma {
3330                    arm_body = Some(expr);
3331                    // Eat a comma if it exists, though.
3332                    let _ = this.eat(exp!(Comma));
3333                    Ok(Recovered::No)
3334                } else if let Some((span, guar)) =
3335                    this.parse_arm_body_missing_braces(&expr, arrow_span)
3336                {
3337                    let body = this.mk_expr_err(span, guar);
3338                    arm_body = Some(body);
3339                    Ok(Recovered::Yes(guar))
3340                } else {
3341                    let expr_span = expr.span;
3342                    arm_body = Some(expr);
3343                    this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map_err(|mut err| {
3344                        if this.token == token::FatArrow {
3345                            let sm = this.psess.source_map();
3346                            if let Ok(expr_lines) = sm.span_to_lines(expr_span)
3347                                && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
3348                                && expr_lines.lines.len() == 2
3349                            {
3350                                if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col {
3351                                    // We check whether there's any trailing code in the parse span,
3352                                    // if there isn't, we very likely have the following:
3353                                    //
3354                                    // X |     &Y => "y"
3355                                    //   |        --    - missing comma
3356                                    //   |        |
3357                                    //   |        arrow_span
3358                                    // X |     &X => "x"
3359                                    //   |      - ^^ self.token.span
3360                                    //   |      |
3361                                    //   |      parsed until here as `"y" & X`
3362                                    err.span_suggestion_short(
3363                                        arm_start_span.shrink_to_hi(),
3364                                        "missing a comma here to end this `match` arm",
3365                                        ",",
3366                                        Applicability::MachineApplicable,
3367                                    );
3368                                } else if arm_start_lines.lines[0].end_col + rustc_span::CharPos(1)
3369                                    == expr_lines.lines[0].end_col
3370                                {
3371                                    // similar to the above, but we may typo a `.` or `/` at the end of the line
3372                                    let comma_span = arm_start_span
3373                                        .shrink_to_hi()
3374                                        .with_hi(arm_start_span.hi() + rustc_span::BytePos(1));
3375                                    if let Ok(res) = sm.span_to_snippet(comma_span)
3376                                        && (res == "." || res == "/")
3377                                    {
3378                                        err.span_suggestion_short(
3379                                            comma_span,
3380                                            "you might have meant to write a `,` to end this `match` arm",
3381                                            ",",
3382                                            Applicability::MachineApplicable,
3383                                        );
3384                                    }
3385                                }
3386                            }
3387                        } else {
3388                            err.span_label(
3389                                arrow_span,
3390                                "while parsing the `match` arm starting here",
3391                            );
3392                        }
3393                        err
3394                    })
3395                }
3396            };
3397
3398            let hi_span = arm_body.as_ref().map_or(span_before_body, |body| body.span);
3399            let arm_span = lo.to(hi_span);
3400
3401            // We want to recover:
3402            // X |     Some(_) => foo()
3403            //   |                     - missing comma
3404            // X |     None => "x"
3405            //   |     ^^^^ self.token.span
3406            // as well as:
3407            // X |     Some(!)
3408            //   |            - missing comma
3409            // X |     None => "x"
3410            //   |     ^^^^ self.token.span
3411            // But we musn't recover
3412            // X |     pat[0] => {}
3413            //   |        ^ self.token.span
3414            let recover_missing_comma = arm_body.is_some() || pat.could_be_never_pattern();
3415            if recover_missing_comma {
3416                result = result.or_else(|err| {
3417                    // FIXME(compiler-errors): We could also recover `; PAT =>` here
3418
3419                    // Try to parse a following `PAT =>`, if successful
3420                    // then we should recover.
3421                    let mut snapshot = this.create_snapshot_for_diagnostic();
3422                    let pattern_follows = snapshot
3423                        .parse_pat_no_top_guard(
3424                            None,
3425                            RecoverComma::Yes,
3426                            RecoverColon::Yes,
3427                            CommaRecoveryMode::EitherTupleOrPipe,
3428                        )
3429                        .map_err(|err| err.cancel())
3430                        .is_ok();
3431                    if pattern_follows && snapshot.check(exp!(FatArrow)) {
3432                        err.cancel();
3433                        let guar = this.dcx().emit_err(errors::MissingCommaAfterMatchArm {
3434                            span: arm_span.shrink_to_hi(),
3435                        });
3436                        return Ok(Recovered::Yes(guar));
3437                    }
3438                    Err(err)
3439                });
3440            }
3441            result?;
3442
3443            Ok((
3444                ast::Arm {
3445                    attrs,
3446                    pat,
3447                    guard,
3448                    body: arm_body,
3449                    span: arm_span,
3450                    id: DUMMY_NODE_ID,
3451                    is_placeholder: false,
3452                },
3453                Trailing::No,
3454                UsePreAttrPos::No,
3455            ))
3456        })
3457    }
3458
3459    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> {
3460        // Used to check the `if_let_guard` feature mostly by scanning
3461        // `&&` tokens.
3462        fn has_let_expr(expr: &Expr) -> bool {
3463            match &expr.kind {
3464                ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => {
3465                    let lhs_rslt = has_let_expr(lhs);
3466                    let rhs_rslt = has_let_expr(rhs);
3467                    lhs_rslt || rhs_rslt
3468                }
3469                ExprKind::Let(..) => true,
3470                _ => false,
3471            }
3472        }
3473        if !self.eat_keyword(exp!(If)) {
3474            // No match arm guard present.
3475            return Ok(None);
3476        }
3477
3478        let if_span = self.prev_token.span;
3479        let mut cond = self.parse_match_guard_condition()?;
3480
3481        CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
3482
3483        if has_let_expr(&cond) {
3484            let span = if_span.to(cond.span);
3485            self.psess.gated_spans.gate(sym::if_let_guard, span);
3486        }
3487        Ok(Some(cond))
3488    }
3489
3490    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
3491        if self.token == token::OpenParen {
3492            let left = self.token.span;
3493            let pat = self.parse_pat_no_top_guard(
3494                None,
3495                RecoverComma::Yes,
3496                RecoverColon::Yes,
3497                CommaRecoveryMode::EitherTupleOrPipe,
3498            )?;
3499            if let ast::PatKind::Paren(subpat) = &pat.kind
3500                && let ast::PatKind::Guard(..) = &subpat.kind
3501            {
3502                // Detect and recover from `($pat if $cond) => $arm`.
3503                // FIXME(guard_patterns): convert this to a normal guard instead
3504                let span = pat.span;
3505                let ast::PatKind::Paren(subpat) = pat.kind else { unreachable!() };
3506                let ast::PatKind::Guard(_, mut cond) = subpat.kind else { unreachable!() };
3507                self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
3508                CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
3509                let right = self.prev_token.span;
3510                self.dcx().emit_err(errors::ParenthesesInMatchPat {
3511                    span: vec![left, right],
3512                    sugg: errors::ParenthesesInMatchPatSugg { left, right },
3513                });
3514                Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))
3515            } else {
3516                Ok((pat, self.parse_match_arm_guard()?))
3517            }
3518        } else {
3519            // Regular parser flow:
3520            let pat = self.parse_pat_no_top_guard(
3521                None,
3522                RecoverComma::Yes,
3523                RecoverColon::Yes,
3524                CommaRecoveryMode::EitherTupleOrPipe,
3525            )?;
3526            Ok((pat, self.parse_match_arm_guard()?))
3527        }
3528    }
3529
3530    fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> {
3531        let attrs = self.parse_outer_attributes()?;
3532        match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
3533            Ok((expr, _)) => Ok(expr),
3534            Err(mut err) => {
3535                if self.prev_token == token::OpenBrace {
3536                    let sugg_sp = self.prev_token.span.shrink_to_lo();
3537                    // Consume everything within the braces, let's avoid further parse
3538                    // errors.
3539                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
3540                    let msg = "you might have meant to start a match arm after the match guard";
3541                    if self.eat(exp!(CloseBrace)) {
3542                        let applicability = if self.token != token::FatArrow {
3543                            // We have high confidence that we indeed didn't have a struct
3544                            // literal in the match guard, but rather we had some operation
3545                            // that ended in a path, immediately followed by a block that was
3546                            // meant to be the match arm.
3547                            Applicability::MachineApplicable
3548                        } else {
3549                            Applicability::MaybeIncorrect
3550                        };
3551                        err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
3552                    }
3553                }
3554                Err(err)
3555            }
3556        }
3557    }
3558
3559    pub(crate) fn is_builtin(&self) -> bool {
3560        self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
3561    }
3562
3563    /// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten).
3564    fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box<Expr>> {
3565        let annotation =
3566            if self.eat_keyword(exp!(Bikeshed)) { Some(self.parse_ty()?) } else { None };
3567
3568        let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
3569        if self.eat_keyword(exp!(Catch)) {
3570            Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
3571        } else {
3572            let span = span_lo.to(body.span);
3573            let gate_sym =
3574                if annotation.is_none() { sym::try_blocks } else { sym::try_blocks_heterogeneous };
3575            self.psess.gated_spans.gate(gate_sym, span);
3576            Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body, annotation), attrs))
3577        }
3578    }
3579
3580    fn is_do_catch_block(&self) -> bool {
3581        self.token.is_keyword(kw::Do)
3582            && self.is_keyword_ahead(1, &[kw::Catch])
3583            && self.look_ahead(2, |t| *t == token::OpenBrace || t.is_metavar_block())
3584            && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
3585    }
3586
3587    fn is_do_yeet(&self) -> bool {
3588        self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet])
3589    }
3590
3591    fn is_try_block(&self) -> bool {
3592        self.token.is_keyword(kw::Try)
3593            && self.look_ahead(1, |t| {
3594                *t == token::OpenBrace
3595                    || t.is_metavar_block()
3596                    || t.kind == TokenKind::Ident(sym::bikeshed, IdentIsRaw::No)
3597            })
3598            && self.token_uninterpolated_span().at_least_rust_2018()
3599    }
3600
3601    /// Parses an `async move? {...}` or `gen move? {...}` expression.
3602    fn parse_gen_block(&mut self) -> PResult<'a, Box<Expr>> {
3603        let lo = self.token.span;
3604        let kind = if self.eat_keyword(exp!(Async)) {
3605            if self.eat_keyword(exp!(Gen)) { GenBlockKind::AsyncGen } else { GenBlockKind::Async }
3606        } else {
3607            assert!(self.eat_keyword(exp!(Gen)));
3608            GenBlockKind::Gen
3609        };
3610        match kind {
3611            GenBlockKind::Async => {
3612                // `async` blocks are stable
3613            }
3614            GenBlockKind::Gen | GenBlockKind::AsyncGen => {
3615                self.psess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span));
3616            }
3617        }
3618        let capture_clause = self.parse_capture_clause()?;
3619        let decl_span = lo.to(self.prev_token.span);
3620        let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
3621        let kind = ExprKind::Gen(capture_clause, body, kind, decl_span);
3622        Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
3623    }
3624
3625    fn is_gen_block(&self, kw: Symbol, lookahead: usize) -> bool {
3626        self.is_keyword_ahead(lookahead, &[kw])
3627            && ((
3628                // `async move {`
3629                self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use])
3630                    && self.look_ahead(lookahead + 2, |t| {
3631                        *t == token::OpenBrace || t.is_metavar_block()
3632                    })
3633            ) || (
3634                // `async {`
3635                self.look_ahead(lookahead + 1, |t| *t == token::OpenBrace || t.is_metavar_block())
3636            ))
3637    }
3638
3639    pub(super) fn is_async_gen_block(&self) -> bool {
3640        self.token.is_keyword(kw::Async) && self.is_gen_block(kw::Gen, 1)
3641    }
3642
3643    fn is_likely_struct_lit(&self) -> bool {
3644        // `{ ident, ` and `{ ident: ` cannot start a block.
3645        self.look_ahead(1, |t| t.is_ident())
3646            && self.look_ahead(2, |t| t == &token::Comma || t == &token::Colon)
3647    }
3648
3649    fn maybe_parse_struct_expr(
3650        &mut self,
3651        qself: &Option<Box<ast::QSelf>>,
3652        path: &ast::Path,
3653    ) -> Option<PResult<'a, Box<Expr>>> {
3654        let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
3655        match (struct_allowed, self.is_likely_struct_lit()) {
3656            // A struct literal isn't expected and one is pretty much assured not to be present. The
3657            // only situation that isn't detected is when a struct with a single field was attempted
3658            // in a place where a struct literal wasn't expected, but regular parser errors apply.
3659            // Happy path.
3660            (false, false) => None,
3661            (true, _) => {
3662                // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for
3663                // any kind of recovery. Happy path.
3664                if let Err(err) = self.expect(exp!(OpenBrace)) {
3665                    return Some(Err(err));
3666                }
3667                Some(self.parse_expr_struct(qself.clone(), path.clone(), true))
3668            }
3669            (false, true) => {
3670                // We have something like `match foo { bar,` or `match foo { bar:`, which means the
3671                // user might have meant to write a struct literal as part of the `match`
3672                // discriminant. This is done purely for error recovery.
3673                let snapshot = self.create_snapshot_for_diagnostic();
3674                if let Err(err) = self.expect(exp!(OpenBrace)) {
3675                    return Some(Err(err));
3676                }
3677                match self.parse_expr_struct(qself.clone(), path.clone(), false) {
3678                    Ok(expr) => {
3679                        // This is a struct literal, but we don't accept them here.
3680                        self.dcx().emit_err(errors::StructLiteralNotAllowedHere {
3681                            span: expr.span,
3682                            sub: errors::StructLiteralNotAllowedHereSugg {
3683                                left: path.span.shrink_to_lo(),
3684                                right: expr.span.shrink_to_hi(),
3685                            },
3686                        });
3687                        Some(Ok(expr))
3688                    }
3689                    Err(err) => {
3690                        // We couldn't parse a valid struct, rollback and let the parser emit an
3691                        // error elsewhere.
3692                        err.cancel();
3693                        self.restore_snapshot(snapshot);
3694                        None
3695                    }
3696                }
3697            }
3698        }
3699    }
3700
3701    pub(super) fn parse_struct_fields(
3702        &mut self,
3703        pth: ast::Path,
3704        recover: bool,
3705        close: ExpTokenPair,
3706    ) -> PResult<
3707        'a,
3708        (
3709            ThinVec<ExprField>,
3710            ast::StructRest,
3711            Option<ErrorGuaranteed>, /* async blocks are forbidden in Rust 2015 */
3712        ),
3713    > {
3714        let mut fields = ThinVec::new();
3715        let mut base = ast::StructRest::None;
3716        let mut recovered_async = None;
3717        let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
3718
3719        let async_block_err = |e: &mut Diag<'_>, span: Span| {
3720            errors::AsyncBlockIn2015 { span }.add_to_diag(e);
3721            errors::HelpUseLatestEdition::new().add_to_diag(e);
3722        };
3723
3724        while self.token != close.tok {
3725            if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(&close.tok) {
3726                let exp_span = self.prev_token.span;
3727                // We permit `.. }` on the left-hand side of a destructuring assignment.
3728                if self.check(close) {
3729                    base = ast::StructRest::Rest(self.prev_token.span);
3730                    break;
3731                }
3732                match self.parse_expr() {
3733                    Ok(e) => base = ast::StructRest::Base(e),
3734                    Err(e) if recover => {
3735                        e.emit();
3736                        self.recover_stmt();
3737                    }
3738                    Err(e) => return Err(e),
3739                }
3740                self.recover_struct_comma_after_dotdot(exp_span);
3741                break;
3742            }
3743
3744            // Peek the field's ident before parsing its expr in order to emit better diagnostics.
3745            let peek = self
3746                .token
3747                .ident()
3748                .filter(|(ident, is_raw)| {
3749                    (!ident.is_reserved() || matches!(is_raw, IdentIsRaw::Yes))
3750                        && self.look_ahead(1, |tok| *tok == token::Colon)
3751                })
3752                .map(|(ident, _)| ident);
3753
3754            // We still want a field even if its expr didn't parse.
3755            let field_ident = |this: &Self, guar: ErrorGuaranteed| {
3756                peek.map(|ident| {
3757                    let span = ident.span;
3758                    ExprField {
3759                        ident,
3760                        span,
3761                        expr: this.mk_expr_err(span, guar),
3762                        is_shorthand: false,
3763                        attrs: AttrVec::new(),
3764                        id: DUMMY_NODE_ID,
3765                        is_placeholder: false,
3766                    }
3767                })
3768            };
3769
3770            let parsed_field = match self.parse_expr_field() {
3771                Ok(f) => Ok(f),
3772                Err(mut e) => {
3773                    if pth == kw::Async {
3774                        async_block_err(&mut e, pth.span);
3775                    } else {
3776                        e.span_label(pth.span, "while parsing this struct");
3777                    }
3778
3779                    if let Some((ident, _)) = self.token.ident()
3780                        && !self.token.is_reserved_ident()
3781                        && self.look_ahead(1, |t| {
3782                            AssocOp::from_token(t).is_some()
3783                                || matches!(
3784                                    t.kind,
3785                                    token::OpenParen | token::OpenBracket | token::OpenBrace
3786                                )
3787                                || *t == token::Dot
3788                        })
3789                    {
3790                        // Looks like they tried to write a shorthand, complex expression,
3791                        // E.g.: `n + m`, `f(a)`, `a[i]`, `S { x: 3 }`, or `x.y`.
3792                        e.span_suggestion_verbose(
3793                            self.token.span.shrink_to_lo(),
3794                            "try naming a field",
3795                            &format!("{ident}: ",),
3796                            Applicability::MaybeIncorrect,
3797                        );
3798                    }
3799                    if in_if_guard && close.token_type == TokenType::CloseBrace {
3800                        return Err(e);
3801                    }
3802
3803                    if !recover {
3804                        return Err(e);
3805                    }
3806
3807                    let guar = e.emit();
3808                    if pth == kw::Async {
3809                        recovered_async = Some(guar);
3810                    }
3811
3812                    // If the next token is a comma, then try to parse
3813                    // what comes next as additional fields, rather than
3814                    // bailing out until next `}`.
3815                    if self.token != token::Comma {
3816                        self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
3817                        if self.token != token::Comma {
3818                            break;
3819                        }
3820                    }
3821
3822                    Err(guar)
3823                }
3824            };
3825
3826            let is_shorthand = parsed_field.as_ref().is_ok_and(|f| f.is_shorthand);
3827            // A shorthand field can be turned into a full field with `:`.
3828            // We should point this out.
3829            self.check_or_expected(!is_shorthand, TokenType::Colon);
3830
3831            match self.expect_one_of(&[exp!(Comma)], &[close]) {
3832                Ok(_) => {
3833                    if let Ok(f) = parsed_field.or_else(|guar| field_ident(self, guar).ok_or(guar))
3834                    {
3835                        // Only include the field if there's no parse error for the field name.
3836                        fields.push(f);
3837                    }
3838                }
3839                Err(mut e) => {
3840                    if pth == kw::Async {
3841                        async_block_err(&mut e, pth.span);
3842                    } else {
3843                        e.span_label(pth.span, "while parsing this struct");
3844                        if peek.is_some() {
3845                            e.span_suggestion(
3846                                self.prev_token.span.shrink_to_hi(),
3847                                "try adding a comma",
3848                                ",",
3849                                Applicability::MachineApplicable,
3850                            );
3851                        }
3852                    }
3853                    if !recover {
3854                        return Err(e);
3855                    }
3856                    let guar = e.emit();
3857                    if pth == kw::Async {
3858                        recovered_async = Some(guar);
3859                    } else if let Some(f) = field_ident(self, guar) {
3860                        fields.push(f);
3861                    }
3862                    self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
3863                    let _ = self.eat(exp!(Comma));
3864                }
3865            }
3866        }
3867        Ok((fields, base, recovered_async))
3868    }
3869
3870    /// Precondition: already parsed the '{'.
3871    pub(super) fn parse_expr_struct(
3872        &mut self,
3873        qself: Option<Box<ast::QSelf>>,
3874        pth: ast::Path,
3875        recover: bool,
3876    ) -> PResult<'a, Box<Expr>> {
3877        let lo = pth.span;
3878        let (fields, base, recovered_async) =
3879            self.parse_struct_fields(pth.clone(), recover, exp!(CloseBrace))?;
3880        let span = lo.to(self.token.span);
3881        self.expect(exp!(CloseBrace))?;
3882        let expr = if let Some(guar) = recovered_async {
3883            ExprKind::Err(guar)
3884        } else {
3885            ExprKind::Struct(Box::new(ast::StructExpr { qself, path: pth, fields, rest: base }))
3886        };
3887        Ok(self.mk_expr(span, expr))
3888    }
3889
3890    fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
3891        if self.token != token::Comma {
3892            return;
3893        }
3894        self.dcx().emit_err(errors::CommaAfterBaseStruct {
3895            span: span.to(self.prev_token.span),
3896            comma: self.token.span,
3897        });
3898        self.recover_stmt();
3899    }
3900
3901    fn recover_struct_field_dots(&mut self, close: &TokenKind) -> bool {
3902        if !self.look_ahead(1, |t| t == close) && self.eat(exp!(DotDotDot)) {
3903            // recover from typo of `...`, suggest `..`
3904            let span = self.prev_token.span;
3905            self.dcx().emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
3906            return true;
3907        }
3908        false
3909    }
3910
3911    /// Converts an ident into 'label and emits an "expected a label, found an identifier" error.
3912    fn recover_ident_into_label(&mut self, ident: Ident) -> Label {
3913        // Convert `label` -> `'label`,
3914        // so that nameres doesn't complain about non-existing label
3915        let label = format!("'{}", ident.name);
3916        let ident = Ident::new(Symbol::intern(&label), ident.span);
3917
3918        self.dcx().emit_err(errors::ExpectedLabelFoundIdent {
3919            span: ident.span,
3920            start: ident.span.shrink_to_lo(),
3921        });
3922
3923        Label { ident }
3924    }
3925
3926    /// Parses `ident (COLON expr)?`.
3927    fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
3928        let attrs = self.parse_outer_attributes()?;
3929        self.recover_vcs_conflict_marker();
3930        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
3931            let lo = this.token.span;
3932
3933            // Check if a colon exists one ahead. This means we're parsing a fieldname.
3934            let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
3935            // Proactively check whether parsing the field will be incorrect.
3936            let is_wrong = this.token.is_non_reserved_ident()
3937                && !this.look_ahead(1, |t| {
3938                    t == &token::Colon
3939                        || t == &token::Eq
3940                        || t == &token::Comma
3941                        || t == &token::CloseBrace
3942                        || t == &token::CloseParen
3943                });
3944            if is_wrong {
3945                return Err(this.dcx().create_err(errors::ExpectedStructField {
3946                    span: this.look_ahead(1, |t| t.span),
3947                    ident_span: this.token.span,
3948                    token: this.look_ahead(1, |t| *t),
3949                }));
3950            }
3951            let (ident, expr) = if is_shorthand {
3952                // Mimic `x: x` for the `x` field shorthand.
3953                let ident = this.parse_ident_common(false)?;
3954                let path = ast::Path::from_ident(ident);
3955                (ident, this.mk_expr(ident.span, ExprKind::Path(None, path)))
3956            } else {
3957                let ident = this.parse_field_name()?;
3958                this.error_on_eq_field_init(ident);
3959                this.bump(); // `:`
3960                (ident, this.parse_expr()?)
3961            };
3962
3963            Ok((
3964                ast::ExprField {
3965                    ident,
3966                    span: lo.to(expr.span),
3967                    expr,
3968                    is_shorthand,
3969                    attrs,
3970                    id: DUMMY_NODE_ID,
3971                    is_placeholder: false,
3972                },
3973                Trailing::from(this.token == token::Comma),
3974                UsePreAttrPos::No,
3975            ))
3976        })
3977    }
3978
3979    /// Check for `=`. This means the source incorrectly attempts to
3980    /// initialize a field with an eq rather than a colon.
3981    fn error_on_eq_field_init(&self, field_name: Ident) {
3982        if self.token != token::Eq {
3983            return;
3984        }
3985
3986        self.dcx().emit_err(errors::EqFieldInit {
3987            span: self.token.span,
3988            eq: field_name.span.shrink_to_hi().to(self.token.span),
3989        });
3990    }
3991
3992    fn err_dotdotdot_syntax(&self, span: Span) {
3993        self.dcx().emit_err(errors::DotDotDot { span });
3994    }
3995
3996    fn err_larrow_operator(&self, span: Span) {
3997        self.dcx().emit_err(errors::LeftArrowOperator { span });
3998    }
3999
4000    fn mk_assign_op(&self, assign_op: AssignOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
4001        ExprKind::AssignOp(assign_op, lhs, rhs)
4002    }
4003
4004    fn mk_range(
4005        &mut self,
4006        start: Option<Box<Expr>>,
4007        end: Option<Box<Expr>>,
4008        limits: RangeLimits,
4009    ) -> ExprKind {
4010        if end.is_none() && limits == RangeLimits::Closed {
4011            let guar = self.inclusive_range_with_incorrect_end();
4012            ExprKind::Err(guar)
4013        } else {
4014            ExprKind::Range(start, end, limits)
4015        }
4016    }
4017
4018    fn mk_unary(&self, unop: UnOp, expr: Box<Expr>) -> ExprKind {
4019        ExprKind::Unary(unop, expr)
4020    }
4021
4022    fn mk_binary(&self, binop: BinOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
4023        ExprKind::Binary(binop, lhs, rhs)
4024    }
4025
4026    fn mk_index(&self, expr: Box<Expr>, idx: Box<Expr>, brackets_span: Span) -> ExprKind {
4027        ExprKind::Index(expr, idx, brackets_span)
4028    }
4029
4030    fn mk_call(&self, f: Box<Expr>, args: ThinVec<Box<Expr>>) -> ExprKind {
4031        ExprKind::Call(f, args)
4032    }
4033
4034    fn mk_await_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
4035        let span = lo.to(self.prev_token.span);
4036        let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span));
4037        self.recover_from_await_method_call();
4038        await_expr
4039    }
4040
4041    fn mk_use_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
4042        let span = lo.to(self.prev_token.span);
4043        let use_expr = self.mk_expr(span, ExprKind::Use(self_arg, self.prev_token.span));
4044        self.recover_from_use();
4045        use_expr
4046    }
4047
4048    pub(crate) fn mk_expr_with_attrs(
4049        &self,
4050        span: Span,
4051        kind: ExprKind,
4052        attrs: AttrVec,
4053    ) -> Box<Expr> {
4054        Box::new(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
4055    }
4056
4057    pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> Box<Expr> {
4058        self.mk_expr_with_attrs(span, kind, AttrVec::new())
4059    }
4060
4061    pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Expr> {
4062        self.mk_expr(span, ExprKind::Err(guar))
4063    }
4064
4065    pub(crate) fn mk_unit_expr(&self, span: Span) -> Box<Expr> {
4066        self.mk_expr(span, ExprKind::Tup(Default::default()))
4067    }
4068
4069    pub(crate) fn mk_closure_expr(&self, span: Span, body: Box<Expr>) -> Box<Expr> {
4070        self.mk_expr(
4071            span,
4072            ast::ExprKind::Closure(Box::new(ast::Closure {
4073                binder: rustc_ast::ClosureBinder::NotPresent,
4074                constness: rustc_ast::Const::No,
4075                movability: rustc_ast::Movability::Movable,
4076                capture_clause: rustc_ast::CaptureBy::Ref,
4077                coroutine_kind: None,
4078                fn_decl: Box::new(rustc_ast::FnDecl {
4079                    inputs: Default::default(),
4080                    output: rustc_ast::FnRetTy::Default(span),
4081                }),
4082                fn_arg_span: span,
4083                fn_decl_span: span,
4084                body,
4085            })),
4086        )
4087    }
4088
4089    /// Create expression span ensuring the span of the parent node
4090    /// is larger than the span of lhs and rhs, including the attributes.
4091    fn mk_expr_sp(&self, lhs: &Box<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
4092        lhs.attrs
4093            .iter()
4094            .find(|a| a.style == AttrStyle::Outer)
4095            .map_or(lhs_span, |a| a.span)
4096            .to(op_span)
4097            .to(rhs_span)
4098    }
4099
4100    fn collect_tokens_for_expr(
4101        &mut self,
4102        attrs: AttrWrapper,
4103        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, Box<Expr>>,
4104    ) -> PResult<'a, Box<Expr>> {
4105        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
4106            let res = f(this, attrs)?;
4107            let trailing = Trailing::from(
4108                this.restrictions.contains(Restrictions::STMT_EXPR)
4109                     && this.token == token::Semi
4110                // FIXME: pass an additional condition through from the place
4111                // where we know we need a comma, rather than assuming that
4112                // `#[attr] expr,` always captures a trailing comma.
4113                || this.token == token::Comma,
4114            );
4115            Ok((res, trailing, UsePreAttrPos::No))
4116        })
4117    }
4118}
4119
4120/// Could this lifetime/label be an unclosed char literal? For example, `'a`
4121/// could be, but `'abc` could not.
4122pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool {
4123    ident.name.as_str().starts_with('\'')
4124        && unescape_char(ident.without_first_quote().name.as_str()).is_ok()
4125}
4126
4127/// Used to forbid `let` expressions in certain syntactic locations.
4128#[derive(Clone, Copy, Subdiagnostic)]
4129pub(crate) enum ForbiddenLetReason {
4130    /// `let` is not valid and the source environment is not important
4131    OtherForbidden,
4132    /// A let chain with the `||` operator
4133    #[note(parse_not_supported_or)]
4134    NotSupportedOr(#[primary_span] Span),
4135    /// A let chain with invalid parentheses
4136    ///
4137    /// For example, `let 1 = 1 && (expr && expr)` is allowed
4138    /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
4139    #[note(parse_not_supported_parentheses)]
4140    NotSupportedParentheses(#[primary_span] Span),
4141}
4142
4143/// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on
4144/// 2024 and later). In case of edition dependence, specify the currently present edition.
4145pub enum LetChainsPolicy {
4146    AlwaysAllowed,
4147    EditionDependent { current_edition: Edition },
4148}
4149
4150/// Visitor to check for invalid use of `ExprKind::Let` that can't
4151/// easily be caught in parsing. For example:
4152///
4153/// ```rust,ignore (example)
4154/// // Only know that the let isn't allowed once the `||` token is reached
4155/// if let Some(x) = y || true {}
4156/// // Only know that the let isn't allowed once the second `=` token is reached.
4157/// if let Some(x) = y && z = 1 {}
4158/// ```
4159struct CondChecker<'a> {
4160    parser: &'a Parser<'a>,
4161    let_chains_policy: LetChainsPolicy,
4162    depth: u32,
4163    forbid_let_reason: Option<ForbiddenLetReason>,
4164    missing_let: Option<errors::MaybeMissingLet>,
4165    comparison: Option<errors::MaybeComparison>,
4166}
4167
4168impl<'a> CondChecker<'a> {
4169    fn new(parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy) -> Self {
4170        CondChecker {
4171            parser,
4172            forbid_let_reason: None,
4173            missing_let: None,
4174            comparison: None,
4175            let_chains_policy,
4176            depth: 0,
4177        }
4178    }
4179}
4180
4181impl MutVisitor for CondChecker<'_> {
4182    fn visit_expr(&mut self, e: &mut Expr) {
4183        self.depth += 1;
4184        use ForbiddenLetReason::*;
4185
4186        let span = e.span;
4187        match e.kind {
4188            ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => {
4189                if let Some(reason) = self.forbid_let_reason {
4190                    let error = match reason {
4191                        NotSupportedOr(or_span) => {
4192                            self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span })
4193                        }
4194                        _ => self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet {
4195                            span,
4196                            reason,
4197                            missing_let: self.missing_let,
4198                            comparison: self.comparison,
4199                        }),
4200                    };
4201                    *recovered = Recovered::Yes(error);
4202                } else if self.depth > 1 {
4203                    // Top level `let` is always allowed; only gate chains
4204                    match self.let_chains_policy {
4205                        LetChainsPolicy::AlwaysAllowed => (),
4206                        LetChainsPolicy::EditionDependent { current_edition } => {
4207                            if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() {
4208                                self.parser.dcx().emit_err(errors::LetChainPre2024 { span });
4209                            }
4210                        }
4211                    }
4212                }
4213            }
4214            ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
4215                mut_visit::walk_expr(self, e);
4216            }
4217            ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _)
4218                if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason =>
4219            {
4220                let forbid_let_reason = self.forbid_let_reason;
4221                self.forbid_let_reason = Some(NotSupportedOr(or_span));
4222                mut_visit::walk_expr(self, e);
4223                self.forbid_let_reason = forbid_let_reason;
4224            }
4225            ExprKind::Paren(ref inner)
4226                if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason =>
4227            {
4228                let forbid_let_reason = self.forbid_let_reason;
4229                self.forbid_let_reason = Some(NotSupportedParentheses(inner.span));
4230                mut_visit::walk_expr(self, e);
4231                self.forbid_let_reason = forbid_let_reason;
4232            }
4233            ExprKind::Assign(ref lhs, _, span) => {
4234                let forbid_let_reason = self.forbid_let_reason;
4235                self.forbid_let_reason = Some(OtherForbidden);
4236                let missing_let = self.missing_let;
4237                if let ExprKind::Binary(_, _, rhs) = &lhs.kind
4238                    && let ExprKind::Path(_, _)
4239                    | ExprKind::Struct(_)
4240                    | ExprKind::Call(_, _)
4241                    | ExprKind::Array(_) = rhs.kind
4242                {
4243                    self.missing_let =
4244                        Some(errors::MaybeMissingLet { span: rhs.span.shrink_to_lo() });
4245                }
4246                let comparison = self.comparison;
4247                self.comparison = Some(errors::MaybeComparison { span: span.shrink_to_hi() });
4248                mut_visit::walk_expr(self, e);
4249                self.forbid_let_reason = forbid_let_reason;
4250                self.missing_let = missing_let;
4251                self.comparison = comparison;
4252            }
4253            ExprKind::Unary(_, _)
4254            | ExprKind::Await(_, _)
4255            | ExprKind::Use(_, _)
4256            | ExprKind::AssignOp(_, _, _)
4257            | ExprKind::Range(_, _, _)
4258            | ExprKind::Try(_)
4259            | ExprKind::AddrOf(_, _, _)
4260            | ExprKind::Binary(_, _, _)
4261            | ExprKind::Field(_, _)
4262            | ExprKind::Index(_, _, _)
4263            | ExprKind::Call(_, _)
4264            | ExprKind::MethodCall(_)
4265            | ExprKind::Tup(_)
4266            | ExprKind::Paren(_) => {
4267                let forbid_let_reason = self.forbid_let_reason;
4268                self.forbid_let_reason = Some(OtherForbidden);
4269                mut_visit::walk_expr(self, e);
4270                self.forbid_let_reason = forbid_let_reason;
4271            }
4272            ExprKind::Cast(ref mut op, _)
4273            | ExprKind::Type(ref mut op, _)
4274            | ExprKind::UnsafeBinderCast(_, ref mut op, _) => {
4275                let forbid_let_reason = self.forbid_let_reason;
4276                self.forbid_let_reason = Some(OtherForbidden);
4277                self.visit_expr(op);
4278                self.forbid_let_reason = forbid_let_reason;
4279            }
4280            ExprKind::Let(_, _, _, Recovered::Yes(_))
4281            | ExprKind::Array(_)
4282            | ExprKind::ConstBlock(_)
4283            | ExprKind::Lit(_)
4284            | ExprKind::If(_, _, _)
4285            | ExprKind::While(_, _, _)
4286            | ExprKind::ForLoop { .. }
4287            | ExprKind::Loop(_, _, _)
4288            | ExprKind::Match(_, _, _)
4289            | ExprKind::Closure(_)
4290            | ExprKind::Block(_, _)
4291            | ExprKind::Gen(_, _, _, _)
4292            | ExprKind::TryBlock(_, _)
4293            | ExprKind::Underscore
4294            | ExprKind::Path(_, _)
4295            | ExprKind::Break(_, _)
4296            | ExprKind::Continue(_)
4297            | ExprKind::Ret(_)
4298            | ExprKind::InlineAsm(_)
4299            | ExprKind::OffsetOf(_, _)
4300            | ExprKind::MacCall(_)
4301            | ExprKind::Struct(_)
4302            | ExprKind::Repeat(_, _)
4303            | ExprKind::Yield(_)
4304            | ExprKind::Yeet(_)
4305            | ExprKind::Become(_)
4306            | ExprKind::IncludedBytes(_)
4307            | ExprKind::FormatArgs(_)
4308            | ExprKind::Err(_)
4309            | ExprKind::Dummy => {
4310                // These would forbid any let expressions they contain already.
4311            }
4312        }
4313        self.depth -= 1;
4314    }
4315}