// ignore-tidy-filelength

use core::mem;
use core::ops::{Bound, ControlFlow};

use ast::mut_visit::{self, MutVisitor};
use ast::token::IdentIsRaw;
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind};
use rustc_ast::tokenstream::TokenTree;
use rustc_ast::util::case::Case;
use rustc_ast::util::classify;
use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par};
use rustc_ast::visit::{Visitor, walk_expr};
use rustc_ast::{
    self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind,
    BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl,
    FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits,
    StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
use rustc_literal_escaper::unescape_char;
use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Spanned, Symbol, kw, respan, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::instrument;

use super::diagnostics::SnapshotParser;
use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
    AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle,
    Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos,
};
use crate::{errors, exp, maybe_recover_from_interpolated_ty_qpath};

#[derive(Debug)]
pub(super) enum DestructuredFloat {
    /// 1e2
    Single(Symbol, Span),
    /// 1.
    TrailingDot(Symbol, Span, Span),
    /// 1.2 | 1.2e3
    MiddleDot(Symbol, Span, Span, Symbol, Span),
    /// Invalid
    Error,
}

impl<'a> Parser<'a> {
    /// Parses an expression.
    #[inline]
    pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> {
        self.current_closure.take();

        let attrs = self.parse_outer_attributes()?;
        self.parse_expr_res(Restrictions::empty(), attrs).map(|res| res.0)
    }

    /// Parses an expression, forcing tokens to be collected.
    pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box<Expr>> {
        self.current_closure.take();

        // If the expression is associative (e.g. `1 + 2`), then any preceding
        // outer attribute actually belongs to the first inner sub-expression.
        // In which case we must use the pre-attr pos to include the attribute
        // in the collected tokens for the outer expression.
        let pre_attr_pos = self.collect_pos();
        let attrs = self.parse_outer_attributes()?;
        self.collect_tokens(
            Some(pre_attr_pos),
            AttrWrapper::empty(),
            ForceCollect::Yes,
            |this, _empty_attrs| {
                let (expr, is_assoc) = this.parse_expr_res(Restrictions::empty(), attrs)?;
                let use_pre_attr_pos =
                    if is_assoc { UsePreAttrPos::Yes } else { UsePreAttrPos::No };
                Ok((expr, Trailing::No, use_pre_attr_pos))
            },
        )
    }

    pub fn parse_expr_anon_const(
        &mut self,
        mgca_disambiguation: impl FnOnce(&Self, &Expr) -> MgcaDisambiguation,
    ) -> PResult<'a, AnonConst> {
        self.parse_expr().map(|value| AnonConst {
            id: DUMMY_NODE_ID,
            mgca_disambiguation: mgca_disambiguation(self, &value),
            value,
        })
    }

    fn parse_expr_catch_underscore(
        &mut self,
        restrictions: Restrictions,
    ) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        match self.parse_expr_res(restrictions, attrs) {
            Ok((expr, _)) => Ok(expr),
            Err(err) => match self.token.ident() {
                Some((Ident { name: kw::Underscore, .. }, IdentIsRaw::No))
                    if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
                {
                    // Special-case handling of `foo(_, _, _)`
                    let guar = err.emit();
                    self.bump();
                    Ok(self.mk_expr(self.prev_token.span, ExprKind::Err(guar)))
                }
                _ => Err(err),
            },
        }
    }

    /// Parses a sequence of expressions delimited by parentheses.
    fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<Box<Expr>>> {
        self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty()))
            .map(|(r, _)| r)
    }

    /// Parses an expression, subject to the given restrictions.
    #[inline]
    pub(super) fn parse_expr_res(
        &mut self,
        r: Restrictions,
        attrs: AttrWrapper,
    ) -> PResult<'a, (Box<Expr>, bool)> {
        self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs))
    }

    /// Parses an associative expression with operators of at least `min_prec` precedence.
    /// The `bool` in the return value indicates if it was an assoc expr, i.e. with an operator
    /// followed by a subexpression (e.g. `1 + 2`).
    pub(super) fn parse_expr_assoc_with(
        &mut self,
        min_prec: Bound<ExprPrecedence>,
        attrs: AttrWrapper,
    ) -> PResult<'a, (Box<Expr>, bool)> {
        let lhs = if self.token.is_range_separator() {
            return self.parse_expr_prefix_range(attrs).map(|res| (res, false));
        } else {
            self.parse_expr_prefix(attrs)?
        };
        self.parse_expr_assoc_rest_with(min_prec, false, lhs)
    }

    /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators
    /// of at least `min_prec` precedence. The `bool` in the return value indicates if something
    /// was actually parsed.
    pub(super) fn parse_expr_assoc_rest_with(
        &mut self,
        min_prec: Bound<ExprPrecedence>,
        starts_stmt: bool,
        mut lhs: Box<Expr>,
    ) -> PResult<'a, (Box<Expr>, bool)> {
        let mut parsed_something = false;
        if !self.should_continue_as_assoc_expr(&lhs) {
            return Ok((lhs, parsed_something));
        }

        self.expected_token_types.insert(TokenType::Operator);
        while let Some(op) = self.check_assoc_op() {
            let lhs_span = self.interpolated_or_expr_span(&lhs);
            let cur_op_span = self.token.span;
            let restrictions = if op.node.is_assign_like() {
                self.restrictions & Restrictions::NO_STRUCT_LITERAL
            } else {
                self.restrictions
            };
            let prec = op.node.precedence();
            if match min_prec {
                Bound::Included(min_prec) => prec < min_prec,
                Bound::Excluded(min_prec) => prec <= min_prec,
                Bound::Unbounded => false,
            } {
                break;
            }
            // Check for deprecated `...` syntax
            if self.token == token::DotDotDot && op.node == AssocOp::Range(RangeLimits::Closed) {
                self.err_dotdotdot_syntax(self.token.span);
            }

            if self.token == token::LArrow {
                self.err_larrow_operator(self.token.span);
            }

            parsed_something = true;
            self.bump();
            if op.node.is_comparison() {
                if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
                    return Ok((expr, parsed_something));
                }
            }

            // Look for JS' `===` and `!==` and recover
            if let AssocOp::Binary(bop @ BinOpKind::Eq | bop @ BinOpKind::Ne) = op.node
                && self.token == token::Eq
                && self.prev_token.span.hi() == self.token.span.lo()
            {
                let sp = op.span.to(self.token.span);
                let sugg = bop.as_str().into();
                let invalid = format!("{sugg}=");
                self.dcx().emit_err(errors::InvalidComparisonOperator {
                    span: sp,
                    invalid: invalid.clone(),
                    sub: errors::InvalidComparisonOperatorSub::Correctable {
                        span: sp,
                        invalid,
                        correct: sugg,
                    },
                });
                self.bump();
            }

            // Look for PHP's `<>` and recover
            if op.node == AssocOp::Binary(BinOpKind::Lt)
                && self.token == token::Gt
                && self.prev_token.span.hi() == self.token.span.lo()
            {
                let sp = op.span.to(self.token.span);
                self.dcx().emit_err(errors::InvalidComparisonOperator {
                    span: sp,
                    invalid: "<>".into(),
                    sub: errors::InvalidComparisonOperatorSub::Correctable {
                        span: sp,
                        invalid: "<>".into(),
                        correct: "!=".into(),
                    },
                });
                self.bump();
            }

            // Look for C++'s `<=>` and recover
            if op.node == AssocOp::Binary(BinOpKind::Le)
                && self.token == token::Gt
                && self.prev_token.span.hi() == self.token.span.lo()
            {
                let sp = op.span.to(self.token.span);
                self.dcx().emit_err(errors::InvalidComparisonOperator {
                    span: sp,
                    invalid: "<=>".into(),
                    sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
                });
                self.bump();
            }

            if self.prev_token == token::Plus
                && self.token == token::Plus
                && self.prev_token.span.between(self.token.span).is_empty()
            {
                let op_span = self.prev_token.span.to(self.token.span);
                // Eat the second `+`
                self.bump();
                lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?;
                continue;
            }

            if self.prev_token == token::Minus
                && self.token == token::Minus
                && self.prev_token.span.between(self.token.span).is_empty()
                && !self.look_ahead(1, |tok| tok.can_begin_expr())
            {
                let op_span = self.prev_token.span.to(self.token.span);
                // Eat the second `-`
                self.bump();
                lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
                continue;
            }

            let op_span = op.span;
            let op = op.node;
            // Special cases:
            if op == AssocOp::Cast {
                lhs = self.parse_assoc_op_cast(lhs, lhs_span, op_span, ExprKind::Cast)?;
                continue;
            } else if let AssocOp::Range(limits) = op {
                // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
                // generalise it to the Fixity::None code.
                lhs = self.parse_expr_range(prec, lhs, limits, cur_op_span)?;
                break;
            }

            let min_prec = match op.fixity() {
                Fixity::Right => Bound::Included(prec),
                Fixity::Left | Fixity::None => Bound::Excluded(prec),
            };
            let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
                let attrs = this.parse_outer_attributes()?;
                this.parse_expr_assoc_with(min_prec, attrs)
            })?;

            let span = self.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span);
            lhs = match op {
                AssocOp::Binary(ast_op) => {
                    let binary = self.mk_binary(respan(cur_op_span, ast_op), lhs, rhs);
                    self.mk_expr(span, binary)
                }
                AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)),
                AssocOp::AssignOp(aop) => {
                    let aopexpr = self.mk_assign_op(respan(cur_op_span, aop), lhs, rhs);
                    self.mk_expr(span, aopexpr)
                }
                AssocOp::Cast | AssocOp::Range(_) => {
                    self.dcx().span_bug(span, "AssocOp should have been handled by special case")
                }
            };
        }

        Ok((lhs, parsed_something))
    }

    fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
        match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
            // Semi-statement forms are odd:
            // See https://github.com/rust-lang/rust/issues/29071
            (true, None) => false,
            (false, _) => true, // Continue parsing the expression.
            // An exhaustive check is done in the following block, but these are checked first
            // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
            // want to keep their span info to improve diagnostics in these cases in a later stage.
            (true, Some(AssocOp::Binary(
                BinOpKind::Mul | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
                BinOpKind::Sub | // `{ 42 } -5`
                BinOpKind::Add | // `{ 42 } + 42` (unary plus)
                BinOpKind::And | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
                BinOpKind::Or | // `{ 42 } || 42` ("logical or" or closure)
                BinOpKind::BitOr // `{ 42 } | 42` or `{ 42 } |x| 42`
            ))) => {
                // These cases are ambiguous and can't be identified in the parser alone.
                //
                // Bitwise AND is left out because guessing intent is hard. We can make
                // suggestions based on the assumption that double-refs are rarely intentional,
                // and closures are distinct enough that they don't get mixed up with their
                // return value.
                let sp = self.psess.source_map().start_point(self.token.span);
                self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
                false
            }
            (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
            (true, Some(_)) => {
                self.error_found_expr_would_be_stmt(lhs);
                true
            }
        }
    }

    /// We've found an expression that would be parsed as a statement,
    /// but the next token implies this should be parsed as an expression.
    /// For example: `if let Some(x) = x { x } else { 0 } / 2`.
    fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
        self.dcx().emit_err(errors::FoundExprWouldBeStmt {
            span: self.token.span,
            token: self.token,
            suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
        });
    }

    /// Possibly translate the current token to an associative operator.
    /// The method does not advance the current token.
    ///
    /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively.
    pub(super) fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
        let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) {
            // When parsing const expressions, stop parsing when encountering `>`.
            (
                Some(
                    AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge)
                    | AssocOp::AssignOp(AssignOpKind::ShrAssign),
                ),
                _,
            ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
                return None;
            }
            // When recovering patterns as expressions, stop parsing when encountering an
            // assignment `=`, an alternative `|`, or a range `..`.
            (
                Some(
                    AssocOp::Assign
                    | AssocOp::AssignOp(_)
                    | AssocOp::Binary(BinOpKind::BitOr)
                    | AssocOp::Range(_),
                ),
                _,
            ) if self.restrictions.contains(Restrictions::IS_PAT) => {
                return None;
            }
            (Some(op), _) => (op, self.token.span),
            (None, Some((Ident { name: sym::and, span }, IdentIsRaw::No)))
                if self.may_recover() =>
            {
                self.dcx().emit_err(errors::InvalidLogicalOperator {
                    span: self.token.span,
                    incorrect: "and".into(),
                    sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
                });
                (AssocOp::Binary(BinOpKind::And), span)
            }
            (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => {
                self.dcx().emit_err(errors::InvalidLogicalOperator {
                    span: self.token.span,
                    incorrect: "or".into(),
                    sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
                });
                (AssocOp::Binary(BinOpKind::Or), span)
            }
            _ => return None,
        };
        Some(respan(span, op))
    }

    /// Checks if this expression is a successfully parsed statement.
    fn expr_is_complete(&self, e: &Expr) -> bool {
        self.restrictions.contains(Restrictions::STMT_EXPR) && classify::expr_is_complete(e)
    }

    /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
    /// The other two variants are handled in `parse_prefix_range_expr` below.
    fn parse_expr_range(
        &mut self,
        prec: ExprPrecedence,
        lhs: Box<Expr>,
        limits: RangeLimits,
        cur_op_span: Span,
    ) -> PResult<'a, Box<Expr>> {
        let rhs = if self.is_at_start_of_range_notation_rhs() {
            let maybe_lt = self.token;
            let attrs = self.parse_outer_attributes()?;
            Some(
                self.parse_expr_assoc_with(Bound::Excluded(prec), attrs)
                    .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?
                    .0,
            )
        } else {
            None
        };
        let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
        let span = self.mk_expr_sp(&lhs, lhs.span, cur_op_span, rhs_span);
        let range = self.mk_range(Some(lhs), rhs, limits);
        Ok(self.mk_expr(span, range))
    }

    fn is_at_start_of_range_notation_rhs(&self) -> bool {
        if self.token.can_begin_expr() {
            // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
            if self.token == token::OpenBrace {
                return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
            }
            true
        } else {
            false
        }
    }

    /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
    fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
        if !attrs.is_empty() {
            let err = errors::DotDotRangeAttribute { span: self.token.span };
            self.dcx().emit_err(err);
        }

        // Check for deprecated `...` syntax.
        if self.token == token::DotDotDot {
            self.err_dotdotdot_syntax(self.token.span);
        }

        debug_assert!(
            self.token.is_range_separator(),
            "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq",
            self.token
        );

        let limits = match self.token.kind {
            token::DotDot => RangeLimits::HalfOpen,
            _ => RangeLimits::Closed,
        };
        let op = AssocOp::from_token(&self.token);
        let attrs = self.parse_outer_attributes()?;
        self.collect_tokens_for_expr(attrs, |this, attrs| {
            let lo = this.token.span;
            let maybe_lt = this.look_ahead(1, |t| t.clone());
            this.bump();
            let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
                // RHS must be parsed with more associativity than the dots.
                let attrs = this.parse_outer_attributes()?;
                this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs)
                    .map(|(x, _)| (lo.to(x.span), Some(x)))
                    .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
            } else {
                (lo, None)
            };
            let range = this.mk_range(None, opt_end, limits);
            Ok(this.mk_expr_with_attrs(span, range, attrs))
        })
    }

    /// Parses a prefix-unary-operator expr.
    fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;

        macro_rules! make_it {
            ($this:ident, $attrs:expr, |this, _| $body:expr) => {
                $this.collect_tokens_for_expr($attrs, |$this, attrs| {
                    let (hi, ex) = $body?;
                    Ok($this.mk_expr_with_attrs(lo.to(hi), ex, attrs))
                })
            };
        }

        let this = self;

        // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
        match this.token.uninterpolate().kind {
            // `!expr`
            token::Bang => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
            // `~expr`
            token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
            // `-expr`
            token::Minus => {
                make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
            }
            // `*expr`
            token::Star => {
                make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
            }
            // `&expr` and `&&expr`
            token::And | token::AndAnd => {
                make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
            }
            // `+lit`
            token::Plus if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
                let mut err = errors::LeadingPlusNotSupported {
                    span: lo,
                    remove_plus: None,
                    add_parentheses: None,
                };

                // a block on the LHS might have been intended to be an expression instead
                if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
                    err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
                } else {
                    err.remove_plus = Some(lo);
                }
                this.dcx().emit_err(err);

                this.bump();
                let attrs = this.parse_outer_attributes()?;
                this.parse_expr_prefix(attrs)
            }
            // Recover from `++x`:
            token::Plus if this.look_ahead(1, |t| *t == token::Plus) => {
                let starts_stmt =
                    this.prev_token == token::Semi || this.prev_token == token::CloseBrace;
                let pre_span = this.token.span.to(this.look_ahead(1, |t| t.span));
                // Eat both `+`s.
                this.bump();
                this.bump();

                let operand_expr = this.parse_expr_dot_or_call(attrs)?;
                this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
            }
            token::Ident(..) if this.token.is_keyword(kw::Box) => {
                make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
            }
            token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
                make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
            }
            _ => return this.parse_expr_dot_or_call(attrs),
        }
    }

    fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, Box<Expr>)> {
        self.bump();
        let attrs = self.parse_outer_attributes()?;
        let expr = if self.token.is_range_separator() {
            self.parse_expr_prefix_range(attrs)
        } else {
            self.parse_expr_prefix(attrs)
        }?;
        let span = self.interpolated_or_expr_span(&expr);
        Ok((lo.to(span), expr))
    }

    fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
        let (span, expr) = self.parse_expr_prefix_common(lo)?;
        Ok((span, self.mk_unary(op, expr)))
    }

    /// Recover on `~expr` in favor of `!expr`.
    fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
        self.dcx().emit_err(errors::TildeAsUnaryOperator(lo));

        self.parse_expr_unary(lo, UnOp::Not)
    }

    /// Parse `box expr` - this syntax has been removed, but we still parse this
    /// for now to provide a more useful error
    fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
        let (span, expr) = self.parse_expr_prefix_common(box_kw)?;
        // Make a multipart suggestion instead of `span_to_snippet` in case source isn't available
        let box_kw_and_lo = box_kw.until(self.interpolated_or_expr_span(&expr));
        let hi = span.shrink_to_hi();
        let sugg = errors::AddBoxNew { box_kw_and_lo, hi };
        let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span, sugg });
        Ok((span, ExprKind::Err(guar)))
    }

    fn is_mistaken_not_ident_negation(&self) -> bool {
        let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind {
            // These tokens can start an expression after `!`, but
            // can't continue an expression after an ident
            token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw),
            token::Literal(..) | token::Pound => true,
            _ => t.is_metavar_expr(),
        };
        self.token.is_ident_named(sym::not) && self.look_ahead(1, token_cannot_continue_expr)
    }

    /// Recover on `not expr` in favor of `!expr`.
    fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
        let negated_token = self.look_ahead(1, |t| *t);

        let sub_diag = if negated_token.is_numeric_lit() {
            errors::NotAsNegationOperatorSub::SuggestNotBitwise
        } else if negated_token.is_bool_lit() {
            errors::NotAsNegationOperatorSub::SuggestNotLogical
        } else {
            errors::NotAsNegationOperatorSub::SuggestNotDefault
        };

        self.dcx().emit_err(errors::NotAsNegationOperator {
            negated: negated_token.span,
            negated_desc: super::token_descr(&negated_token),
            // Span the `not` plus trailing whitespace to avoid
            // trailing whitespace after the `!` in our suggestion
            sub: sub_diag(
                self.psess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
            ),
        });

        self.parse_expr_unary(lo, UnOp::Not)
    }

    /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
    fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
        match self.prev_token.kind {
            token::NtIdent(..) | token::NtLifetime(..) => self.prev_token.span,
            token::CloseInvisible(InvisibleOrigin::MetaVar(_)) => {
                // `expr.span` is the interpolated span, because invisible open
                // and close delims both get marked with the same span, one
                // that covers the entire thing between them. (See
                // `rustc_expand::mbe::transcribe::transcribe`.)
                self.prev_token.span
            }
            _ => expr.span,
        }
    }

    fn parse_assoc_op_cast(
        &mut self,
        lhs: Box<Expr>,
        lhs_span: Span,
        op_span: Span,
        expr_kind: fn(Box<Expr>, Box<Ty>) -> ExprKind,
    ) -> PResult<'a, Box<Expr>> {
        let mk_expr = |this: &mut Self, lhs: Box<Expr>, rhs: Box<Ty>| {
            this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs))
        };

        // Save the state of the parser before parsing type normally, in case there is a
        // LessThan comparison after this cast.
        let parser_snapshot_before_type = self.clone();
        let cast_expr = match self.parse_as_cast_ty() {
            Ok(rhs) => mk_expr(self, lhs, rhs),
            Err(type_err) => {
                if !self.may_recover() {
                    return Err(type_err);
                }

                // Rewind to before attempting to parse the type with generics, to recover
                // from situations like `x as usize < y` in which we first tried to parse
                // `usize < y` as a type with generic arguments.
                let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type);

                // Check for typo of `'a: loop { break 'a }` with a missing `'`.
                match (&lhs.kind, &self.token.kind) {
                    (
                        // `foo: `
                        ExprKind::Path(None, ast::Path { segments, .. }),
                        token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
                    ) if let [segment] = segments.as_slice() => {
                        let snapshot = self.create_snapshot_for_diagnostic();
                        let label = Label {
                            ident: Ident::from_str_and_span(
                                &format!("'{}", segment.ident),
                                segment.ident.span,
                            ),
                        };
                        match self.parse_expr_labeled(label, false) {
                            Ok(expr) => {
                                type_err.cancel();
                                self.dcx().emit_err(errors::MalformedLoopLabel {
                                    span: label.ident.span,
                                    suggestion: label.ident.span.shrink_to_lo(),
                                });
                                return Ok(expr);
                            }
                            Err(err) => {
                                err.cancel();
                                self.restore_snapshot(snapshot);
                            }
                        }
                    }
                    _ => {}
                }

                match self.parse_path(PathStyle::Expr) {
                    Ok(path) => {
                        let span_after_type = parser_snapshot_after_type.token.span;
                        let expr = mk_expr(
                            self,
                            lhs,
                            self.mk_ty(path.span, TyKind::Path(None, path.clone())),
                        );

                        let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
                        match self.token.kind {
                            token::Lt => {
                                self.dcx().emit_err(errors::ComparisonInterpretedAsGeneric {
                                    comparison: self.token.span,
                                    r#type: path,
                                    args: args_span,
                                    suggestion: errors::ComparisonInterpretedAsGenericSugg {
                                        left: expr.span.shrink_to_lo(),
                                        right: expr.span.shrink_to_hi(),
                                    },
                                })
                            }
                            token::Shl => self.dcx().emit_err(errors::ShiftInterpretedAsGeneric {
                                shift: self.token.span,
                                r#type: path,
                                args: args_span,
                                suggestion: errors::ShiftInterpretedAsGenericSugg {
                                    left: expr.span.shrink_to_lo(),
                                    right: expr.span.shrink_to_hi(),
                                },
                            }),
                            _ => {
                                // We can end up here even without `<` being the next token, for
                                // example because `parse_ty_no_plus` returns `Err` on keywords,
                                // but `parse_path` returns `Ok` on them due to error recovery.
                                // Return original error and parser state.
                                *self = parser_snapshot_after_type;
                                return Err(type_err);
                            }
                        };

                        // Successfully parsed the type path leaving a `<` yet to parse.
                        type_err.cancel();

                        // Keep `x as usize` as an expression in AST and continue parsing.
                        expr
                    }
                    Err(path_err) => {
                        // Couldn't parse as a path, return original error and parser state.
                        path_err.cancel();
                        *self = parser_snapshot_after_type;
                        return Err(type_err);
                    }
                }
            }
        };

        // Try to parse a postfix operator such as `.`, `?`, or index (`[]`)
        // after a cast. If one is present, emit an error then return a valid
        // parse tree; For something like `&x as T[0]` will be as if it was
        // written `((&x) as T)[0]`.

        let span = cast_expr.span;

        let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?;

        // Check if an illegal postfix operator has been added after the cast.
        // If the resulting expression is not a cast, it is an illegal postfix operator.
        if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) {
            let msg = format!(
                "cast cannot be followed by {}",
                match with_postfix.kind {
                    ExprKind::Index(..) => "indexing",
                    ExprKind::Try(_) => "`?`",
                    ExprKind::Field(_, _) => "a field access",
                    ExprKind::MethodCall(_) => "a method call",
                    ExprKind::Call(_, _) => "a function call",
                    ExprKind::Await(_, _) => "`.await`",
                    ExprKind::Use(_, _) => "`.use`",
                    ExprKind::Yield(YieldKind::Postfix(_)) => "`.yield`",
                    ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match",
                    ExprKind::Err(_) => return Ok(with_postfix),
                    _ => unreachable!(
                        "did not expect {:?} as an illegal postfix operator following cast",
                        with_postfix.kind
                    ),
                }
            );
            let mut err = self.dcx().struct_span_err(span, msg);

            let suggest_parens = |err: &mut Diag<'_>| {
                let suggestions = vec![
                    (span.shrink_to_lo(), "(".to_string()),
                    (span.shrink_to_hi(), ")".to_string()),
                ];
                err.multipart_suggestion(
                    "try surrounding the expression in parentheses",
                    suggestions,
                    Applicability::MachineApplicable,
                );
            };

            suggest_parens(&mut err);

            err.emit();
        };
        Ok(with_postfix)
    }

    /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
    fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
        self.expect_and()?;
        let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
        let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
        let (borrow_kind, mutbl) = self.parse_borrow_modifiers();
        let attrs = self.parse_outer_attributes()?;
        let expr = if self.token.is_range_separator() {
            self.parse_expr_prefix_range(attrs)
        } else {
            self.parse_expr_prefix(attrs)
        }?;
        let hi = self.interpolated_or_expr_span(&expr);
        let span = lo.to(hi);
        if let Some(lt) = lifetime {
            self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span));
        }

        // Add expected tokens if we parsed `&raw` as an expression.
        // This will make sure we see "expected `const`, `mut`", and
        // guides recovery in case we write `&raw expr`.
        if borrow_kind == ast::BorrowKind::Ref
            && mutbl == ast::Mutability::Not
            && matches!(&expr.kind, ExprKind::Path(None, p) if *p == kw::Raw)
        {
            self.expected_token_types.insert(TokenType::KwMut);
            self.expected_token_types.insert(TokenType::KwConst);
        }

        Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr)))
    }

    fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
        self.dcx().emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
    }

    /// Parse `mut?` or `[ raw | pin ] [ const | mut ]`.
    fn parse_borrow_modifiers(&mut self) -> (ast::BorrowKind, ast::Mutability) {
        if self.check_keyword(exp!(Raw)) && self.look_ahead(1, Token::is_mutability) {
            // `raw [ const | mut ]`.
            let found_raw = self.eat_keyword(exp!(Raw));
            assert!(found_raw);
            let mutability = self.parse_const_or_mut().unwrap();
            (ast::BorrowKind::Raw, mutability)
        } else {
            match self.parse_pin_and_mut() {
                // `mut?`
                (ast::Pinnedness::Not, mutbl) => (ast::BorrowKind::Ref, mutbl),
                // `pin [ const | mut ]`.
                // `pin` has been gated in `self.parse_pin_and_mut()` so we don't
                // need to gate it here.
                (ast::Pinnedness::Pinned, mutbl) => (ast::BorrowKind::Pin, mutbl),
            }
        }
    }

    /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
    fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
        self.collect_tokens_for_expr(attrs, |this, attrs| {
            let base = this.parse_expr_bottom()?;
            let span = this.interpolated_or_expr_span(&base);
            this.parse_expr_dot_or_call_with(attrs, base, span)
        })
    }

    pub(super) fn parse_expr_dot_or_call_with(
        &mut self,
        mut attrs: ast::AttrVec,
        mut e: Box<Expr>,
        lo: Span,
    ) -> PResult<'a, Box<Expr>> {
        let mut res = ensure_sufficient_stack(|| {
            loop {
                let has_question =
                    if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
                        // We are using noexpect here because we don't expect a `?` directly after
                        // a `return` which could be suggested otherwise.
                        self.eat_noexpect(&token::Question)
                    } else {
                        self.eat(exp!(Question))
                    };
                if has_question {
                    // `expr?`
                    e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e));
                    continue;
                }
                let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
                    // We are using noexpect here because we don't expect a `.` directly after
                    // a `return` which could be suggested otherwise.
                    self.eat_noexpect(&token::Dot)
                } else if self.token == TokenKind::RArrow && self.may_recover() {
                    // Recovery for `expr->suffix`.
                    self.bump();
                    let span = self.prev_token.span;
                    self.dcx().emit_err(errors::ExprRArrowCall { span });
                    true
                } else {
                    self.eat(exp!(Dot))
                };
                if has_dot {
                    // expr.f
                    e = self.parse_dot_suffix_expr(lo, e)?;
                    continue;
                }
                if self.expr_is_complete(&e) {
                    return Ok(e);
                }
                e = match self.token.kind {
                    token::OpenParen => self.parse_expr_fn_call(lo, e),
                    token::OpenBracket => self.parse_expr_index(lo, e)?,
                    _ => return Ok(e),
                }
            }
        });

        // Stitch the list of outer attributes onto the return value. A little
        // bit ugly, but the best way given the current code structure.
        if !attrs.is_empty()
            && let Ok(expr) = &mut res
        {
            mem::swap(&mut expr.attrs, &mut attrs);
            expr.attrs.extend(attrs)
        }
        res
    }

    pub(super) fn parse_dot_suffix_expr(
        &mut self,
        lo: Span,
        base: Box<Expr>,
    ) -> PResult<'a, Box<Expr>> {
        // At this point we've consumed something like `expr.` and `self.token` holds the token
        // after the dot.
        match self.token.uninterpolate().kind {
            token::Ident(..) => self.parse_dot_suffix(base, lo),
            token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
                let ident_span = self.token.span;
                self.bump();
                Ok(self.mk_expr_tuple_field_access(lo, ident_span, base, symbol, suffix))
            }
            token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
                Ok(match self.break_up_float(symbol, self.token.span) {
                    // 1e2
                    DestructuredFloat::Single(sym, _sp) => {
                        // `foo.1e2`: a single complete dot access, fully consumed. We end up with
                        // the `1e2` token in `self.prev_token` and the following token in
                        // `self.token`.
                        let ident_span = self.token.span;
                        self.bump();
                        self.mk_expr_tuple_field_access(lo, ident_span, base, sym, suffix)
                    }
                    // 1.
                    DestructuredFloat::TrailingDot(sym, ident_span, dot_span) => {
                        // `foo.1.`: a single complete dot access and the start of another.
                        // We end up with the `sym` (`1`) token in `self.prev_token` and a dot in
                        // `self.token`.
                        assert!(suffix.is_none());
                        self.token = Token::new(token::Ident(sym, IdentIsRaw::No), ident_span);
                        self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing));
                        self.mk_expr_tuple_field_access(lo, ident_span, base, sym, None)
                    }
                    // 1.2 | 1.2e3
                    DestructuredFloat::MiddleDot(
                        sym1,
                        ident1_span,
                        _dot_span,
                        sym2,
                        ident2_span,
                    ) => {
                        // `foo.1.2` (or `foo.1.2e3`): two complete dot accesses. We end up with
                        // the `sym2` (`2` or `2e3`) token in `self.prev_token` and the following
                        // token in `self.token`.
                        let next_token2 =
                            Token::new(token::Ident(sym2, IdentIsRaw::No), ident2_span);
                        self.bump_with((next_token2, self.token_spacing));
                        self.bump();
                        let base1 =
                            self.mk_expr_tuple_field_access(lo, ident1_span, base, sym1, None);
                        self.mk_expr_tuple_field_access(lo, ident2_span, base1, sym2, suffix)
                    }
                    DestructuredFloat::Error => base,
                })
            }
            _ => {
                self.error_unexpected_after_dot();
                Ok(base)
            }
        }
    }

    fn error_unexpected_after_dot(&self) {
        let actual = super::token_descr(&self.token);
        let span = self.token.span;
        let sm = self.psess.source_map();
        let (span, actual) = match (&self.token.kind, self.subparser_name) {
            (token::Eof, Some(_)) if let Ok(snippet) = sm.span_to_snippet(sm.next_point(span)) => {
                (span.shrink_to_hi(), format!("`{}`", snippet))
            }
            (token::CloseInvisible(InvisibleOrigin::MetaVar(_)), _) => {
                // No need to report an error. This case will only occur when parsing a pasted
                // metavariable, and we should have emitted an error when parsing the macro call in
                // the first place. E.g. in this code:
                // ```
                // macro_rules! m { ($e:expr) => { $e }; }
                //
                // fn main() {
                //     let f = 1;
                //     m!(f.);
                // }
                // ```
                // we'll get an error "unexpected token: `)` when parsing the `m!(f.)`, so we don't
                // want to issue a second error when parsing the expansion `«f.»` (where `«`/`»`
                // represent the invisible delimiters).
                self.dcx().span_delayed_bug(span, "bad dot expr in metavariable");
                return;
            }
            _ => (span, actual),
        };
        self.dcx().emit_err(errors::UnexpectedTokenAfterDot { span, actual });
    }

    /// We need an identifier or integer, but the next token is a float.
    /// Break the float into components to extract the identifier or integer.
    ///
    /// See also [`TokenKind::break_two_token_op`] which does similar splitting of `>>` into `>`.
    //
    // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2
    //  parts unless those parts are processed immediately. `TokenCursor` should either
    //  support pushing "future tokens" (would be also helpful to `break_and_eat`), or
    //  we should break everything including floats into more basic proc-macro style
    //  tokens in the lexer (probably preferable).
    pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
        #[derive(Debug)]
        enum FloatComponent {
            IdentLike(String),
            Punct(char),
        }
        use FloatComponent::*;

        let float_str = float.as_str();
        let mut components = Vec::new();
        let mut ident_like = String::new();
        for c in float_str.chars() {
            if c == '_' || c.is_ascii_alphanumeric() {
                ident_like.push(c);
            } else if matches!(c, '.' | '+' | '-') {
                if !ident_like.is_empty() {
                    components.push(IdentLike(mem::take(&mut ident_like)));
                }
                components.push(Punct(c));
            } else {
                panic!("unexpected character in a float token: {c:?}")
            }
        }
        if !ident_like.is_empty() {
            components.push(IdentLike(ident_like));
        }

        // With proc macros the span can refer to anything, the source may be too short,
        // or too long, or non-ASCII. It only makes sense to break our span into components
        // if its underlying text is identical to our float literal.
        let can_take_span_apart =
            || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref();

        match &*components {
            // 1e2
            [IdentLike(i)] => {
                DestructuredFloat::Single(Symbol::intern(i), span)
            }
            // 1.
            [IdentLike(left), Punct('.')] => {
                let (left_span, dot_span) = if can_take_span_apart() {
                    let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
                    let dot_span = span.with_lo(left_span.hi());
                    (left_span, dot_span)
                } else {
                    (span, span)
                };
                let left = Symbol::intern(left);
                DestructuredFloat::TrailingDot(left, left_span, dot_span)
            }
            // 1.2 | 1.2e3
            [IdentLike(left), Punct('.'), IdentLike(right)] => {
                let (left_span, dot_span, right_span) = if can_take_span_apart() {
                    let left_span = span.with_hi(span.lo() + BytePos::from_usize(left.len()));
                    let dot_span = span.with_lo(left_span.hi()).with_hi(left_span.hi() + BytePos(1));
                    let right_span = span.with_lo(dot_span.hi());
                    (left_span, dot_span, right_span)
                } else {
                    (span, span, span)
                };
                let left = Symbol::intern(left);
                let right = Symbol::intern(right);
                DestructuredFloat::MiddleDot(left, left_span, dot_span, right, right_span)
            }
            // 1e+ | 1e- (recovered)
            [IdentLike(_), Punct('+' | '-')] |
            // 1e+2 | 1e-2
            [IdentLike(_), Punct('+' | '-'), IdentLike(_)] |
            // 1.2e+ | 1.2e-
            [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-')] |
            // 1.2e+3 | 1.2e-3
            [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => {
                // See the FIXME about `TokenCursor` above.
                self.error_unexpected_after_dot();
                DestructuredFloat::Error
            }
            _ => panic!("unexpected components in a float token: {components:?}"),
        }
    }

    /// Parse the field access used in offset_of, matched by `$(e:expr)+`.
    /// Currently returns a list of idents. However, it should be possible in
    /// future to also do array indices, which might be arbitrary expressions.
    pub(crate) fn parse_floating_field_access(&mut self) -> PResult<'a, Vec<Ident>> {
        let mut fields = Vec::new();
        let mut trailing_dot = None;

        loop {
            // This is expected to use a metavariable $(args:expr)+, but the builtin syntax
            // could be called directly. Calling `parse_expr` allows this function to only
            // consider `Expr`s.
            let expr = self.parse_expr()?;
            let mut current = &expr;
            let start_idx = fields.len();
            loop {
                match current.kind {
                    ExprKind::Field(ref left, right) => {
                        // Field access is read right-to-left.
                        fields.insert(start_idx, right);
                        trailing_dot = None;
                        current = left;
                    }
                    // Parse this both to give helpful error messages and to
                    // verify it can be done with this parser setup.
                    ExprKind::Index(ref left, ref _right, span) => {
                        self.dcx().emit_err(errors::ArrayIndexInOffsetOf(span));
                        current = left;
                    }
                    ExprKind::Lit(token::Lit {
                        kind: token::Float | token::Integer,
                        symbol,
                        suffix,
                    }) => {
                        if let Some(suffix) = suffix {
                            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
                                span: current.span,
                                suffix,
                            });
                        }
                        match self.break_up_float(symbol, current.span) {
                            // 1e2
                            DestructuredFloat::Single(sym, sp) => {
                                trailing_dot = None;
                                fields.insert(start_idx, Ident::new(sym, sp));
                            }
                            // 1.
                            DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => {
                                assert!(suffix.is_none());
                                trailing_dot = Some(dot_span);
                                fields.insert(start_idx, Ident::new(sym, sym_span));
                            }
                            // 1.2 | 1.2e3
                            DestructuredFloat::MiddleDot(
                                symbol1,
                                span1,
                                _dot_span,
                                symbol2,
                                span2,
                            ) => {
                                trailing_dot = None;
                                fields.insert(start_idx, Ident::new(symbol2, span2));
                                fields.insert(start_idx, Ident::new(symbol1, span1));
                            }
                            DestructuredFloat::Error => {
                                trailing_dot = None;
                                fields.insert(start_idx, Ident::new(symbol, self.prev_token.span));
                            }
                        }
                        break;
                    }
                    ExprKind::Path(None, Path { ref segments, .. }) => {
                        match &segments[..] {
                            [PathSegment { ident, args: None, .. }] => {
                                trailing_dot = None;
                                fields.insert(start_idx, *ident)
                            }
                            _ => {
                                self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
                                break;
                            }
                        }
                        break;
                    }
                    _ => {
                        self.dcx().emit_err(errors::InvalidOffsetOf(current.span));
                        break;
                    }
                }
            }

            if self.token.kind.close_delim().is_some() || self.token.kind == token::Comma {
                break;
            } else if trailing_dot.is_none() {
                // This loop should only repeat if there is a trailing dot.
                self.dcx().emit_err(errors::InvalidOffsetOf(self.token.span));
                break;
            }
        }
        if let Some(dot) = trailing_dot {
            self.dcx().emit_err(errors::InvalidOffsetOf(dot));
        }
        Ok(fields.into_iter().collect())
    }

    fn mk_expr_tuple_field_access(
        &self,
        lo: Span,
        ident_span: Span,
        base: Box<Expr>,
        field: Symbol,
        suffix: Option<Symbol>,
    ) -> Box<Expr> {
        if let Some(suffix) = suffix {
            self.dcx()
                .emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix });
        }
        self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span)))
    }

    /// Parse a function call expression, `expr(...)`.
    fn parse_expr_fn_call(&mut self, lo: Span, fun: Box<Expr>) -> Box<Expr> {
        let snapshot = if self.token == token::OpenParen {
            Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
        } else {
            None
        };
        let open_paren = self.token.span;

        let seq = self
            .parse_expr_paren_seq()
            .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
        match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
            Ok(expr) => expr,
            Err(err) => self.recover_seq_parse_error(exp!(OpenParen), exp!(CloseParen), lo, err),
        }
    }

    /// If we encounter a parser state that looks like the user has written a `struct` literal with
    /// parentheses instead of braces, recover the parser state and provide suggestions.
    #[instrument(skip(self, seq, snapshot), level = "trace")]
    fn maybe_recover_struct_lit_bad_delims(
        &mut self,
        lo: Span,
        open_paren: Span,
        seq: PResult<'a, Box<Expr>>,
        snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
    ) -> PResult<'a, Box<Expr>> {
        match (self.may_recover(), seq, snapshot) {
            (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
                snapshot.bump(); // `(`
                match snapshot.parse_struct_fields(path.clone(), false, exp!(CloseParen)) {
                    Ok((fields, ..)) if snapshot.eat(exp!(CloseParen)) => {
                        // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
                        // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
                        self.restore_snapshot(snapshot);
                        let close_paren = self.prev_token.span;
                        let span = lo.to(close_paren);
                        // filter shorthand fields
                        let fields: Vec<_> =
                            fields.into_iter().filter(|field| !field.is_shorthand).collect();

                        let guar = if !fields.is_empty() &&
                            // `token.kind` should not be compared here.
                            // This is because the `snapshot.token.kind` is treated as the same as
                            // that of the open delim in `TokenTreesReader::parse_token_tree`, even
                            // if they are different.
                            self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
                        {
                            err.cancel();
                            self.dcx()
                                .create_err(errors::ParenthesesWithStructFields {
                                    span,
                                    braces_for_struct: errors::BracesForStructLiteral {
                                        first: open_paren,
                                        second: close_paren,
                                        r#type: path.clone(),
                                    },
                                    no_fields_for_fn: errors::NoFieldsForFnCall {
                                        r#type: path,
                                        fields: fields
                                            .into_iter()
                                            .map(|field| field.span.until(field.expr.span))
                                            .collect(),
                                    },
                                })
                                .emit()
                        } else {
                            err.emit()
                        };
                        Ok(self.mk_expr_err(span, guar))
                    }
                    Ok(_) => Err(err),
                    Err(err2) => {
                        err2.cancel();
                        Err(err)
                    }
                }
            }
            (_, seq, _) => seq,
        }
    }

    /// Parse an indexing expression `expr[...]`.
    fn parse_expr_index(&mut self, lo: Span, base: Box<Expr>) -> PResult<'a, Box<Expr>> {
        let prev_span = self.prev_token.span;
        let open_delim_span = self.token.span;
        self.bump(); // `[`
        let index = self.parse_expr()?;
        self.suggest_missing_semicolon_before_array(prev_span, open_delim_span)?;
        self.expect(exp!(CloseBracket))?;
        Ok(self.mk_expr(
            lo.to(self.prev_token.span),
            self.mk_index(base, index, open_delim_span.to(self.prev_token.span)),
        ))
    }

    /// Assuming we have just parsed `.`, continue parsing into an expression.
    fn parse_dot_suffix(&mut self, self_arg: Box<Expr>, lo: Span) -> PResult<'a, Box<Expr>> {
        if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
            return Ok(self.mk_await_expr(self_arg, lo));
        }

        if self.eat_keyword(exp!(Use)) {
            let use_span = self.prev_token.span;
            self.psess.gated_spans.gate(sym::ergonomic_clones, use_span);
            return Ok(self.mk_use_expr(self_arg, lo));
        }

        // Post-fix match
        if self.eat_keyword(exp!(Match)) {
            let match_span = self.prev_token.span;
            self.psess.gated_spans.gate(sym::postfix_match, match_span);
            return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
        }

        // Parse a postfix `yield`.
        if self.eat_keyword(exp!(Yield)) {
            let yield_span = self.prev_token.span;
            self.psess.gated_spans.gate(sym::yield_expr, yield_span);
            return Ok(
                self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg)))
            );
        }

        let fn_span_lo = self.token.span;
        let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
        self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]);
        self.check_turbofish_missing_angle_brackets(&mut seg);

        if self.check(exp!(OpenParen)) {
            // Method call `expr.f()`
            let args = self.parse_expr_paren_seq()?;
            let fn_span = fn_span_lo.to(self.prev_token.span);
            let span = lo.to(self.prev_token.span);
            Ok(self.mk_expr(
                span,
                ExprKind::MethodCall(Box::new(ast::MethodCall {
                    seg,
                    receiver: self_arg,
                    args,
                    span: fn_span,
                })),
            ))
        } else {
            // Field access `expr.f`
            let span = lo.to(self.prev_token.span);
            if let Some(args) = seg.args {
                // See `StashKey::GenericInFieldExpr` for more info on why we stash this.
                self.dcx()
                    .create_err(errors::FieldExpressionWithGeneric(args.span()))
                    .stash(seg.ident.span, StashKey::GenericInFieldExpr);
            }

            Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident)))
        }
    }

    /// At the bottom (top?) of the precedence hierarchy,
    /// Parses things like parenthesized exprs, macros, `return`, etc.
    ///
    /// N.B., this does not parse outer attributes, and is private because it only works
    /// correctly if called from `parse_expr_dot_or_call`.
    fn parse_expr_bottom(&mut self) -> PResult<'a, Box<Expr>> {
        maybe_recover_from_interpolated_ty_qpath!(self, true);

        let span = self.token.span;
        if let Some(expr) = self.eat_metavar_seq_with_matcher(
            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
            |this| {
                // Force collection (as opposed to just `parse_expr`) is required to avoid the
                // attribute duplication seen in #138478.
                let expr = this.parse_expr_force_collect();
                // FIXME(nnethercote) Sometimes with expressions we get a trailing comma, possibly
                // related to the FIXME in `collect_tokens_for_expr`. Examples are the multi-line
                // `assert_eq!` calls involving arguments annotated with `#[rustfmt::skip]` in
                // `compiler/rustc_index/src/bit_set/tests.rs`.
                if this.token.kind == token::Comma {
                    this.bump();
                }
                expr
            },
        ) {
            return Ok(expr);
        } else if let Some(lit) =
            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
        {
            return Ok(lit);
        } else if let Some(block) =
            self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block())
        {
            return Ok(self.mk_expr(span, ExprKind::Block(block, None)));
        } else if let Some(path) =
            self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type))
        {
            return Ok(self.mk_expr(span, ExprKind::Path(None, path)));
        }

        // Outer attributes are already parsed and will be
        // added to the return value after the fact.

        let restrictions = self.restrictions;
        self.with_res(restrictions - Restrictions::ALLOW_LET, |this| {
            // Note: adding new syntax here? Don't forget to adjust `TokenKind::can_begin_expr()`.
            let lo = this.token.span;
            if let token::Literal(_) = this.token.kind {
                // This match arm is a special-case of the `_` match arm below and
                // could be removed without changing functionality, but it's faster
                // to have it here, especially for programs with large constants.
                this.parse_expr_lit()
            } else if this.check(exp!(OpenParen)) {
                this.parse_expr_tuple_parens(restrictions)
            } else if this.check(exp!(OpenBrace)) {
                if let Some(expr) = this.maybe_recover_bad_struct_literal_path(false)? {
                    return Ok(expr);
                }
                this.parse_expr_block(None, lo, BlockCheckMode::Default)
            } else if this.check(exp!(Or)) || this.check(exp!(OrOr)) {
                this.parse_expr_closure().map_err(|mut err| {
                    // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
                    // then suggest parens around the lhs.
                    if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
                    }
                    err
                })
            } else if this.check(exp!(OpenBracket)) {
                this.parse_expr_array_or_repeat(exp!(CloseBracket))
            } else if this.is_builtin() {
                this.parse_expr_builtin()
            } else if this.check_path() {
                this.parse_expr_path_start()
            } else if this.check_keyword(exp!(Move))
                || this.check_keyword(exp!(Use))
                || this.check_keyword(exp!(Static))
                || this.check_const_closure()
            {
                this.parse_expr_closure()
            } else if this.eat_keyword(exp!(If)) {
                this.parse_expr_if()
            } else if this.check_keyword(exp!(For)) {
                if this.choose_generics_over_qpath(1) {
                    this.parse_expr_closure()
                } else {
                    assert!(this.eat_keyword(exp!(For)));
                    this.parse_expr_for(None, lo)
                }
            } else if this.eat_keyword(exp!(While)) {
                this.parse_expr_while(None, lo)
            } else if let Some(label) = this.eat_label() {
                this.parse_expr_labeled(label, true)
            } else if this.eat_keyword(exp!(Loop)) {
                this.parse_expr_loop(None, lo).map_err(|mut err| {
                    err.span_label(lo, "while parsing this `loop` expression");
                    err
                })
            } else if this.eat_keyword(exp!(Match)) {
                this.parse_expr_match().map_err(|mut err| {
                    err.span_label(lo, "while parsing this `match` expression");
                    err
                })
            } else if this.eat_keyword(exp!(Unsafe)) {
                this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
                    |mut err| {
                        err.span_label(lo, "while parsing this `unsafe` expression");
                        err
                    },
                )
            } else if this.check_inline_const(0) {
                this.parse_const_block(lo, false)
            } else if this.may_recover() && this.is_do_catch_block() {
                this.recover_do_catch()
            } else if this.is_try_block() {
                this.expect_keyword(exp!(Try))?;
                this.parse_try_block(lo)
            } else if this.eat_keyword(exp!(Return)) {
                this.parse_expr_return()
            } else if this.eat_keyword(exp!(Continue)) {
                this.parse_expr_continue(lo)
            } else if this.eat_keyword(exp!(Break)) {
                this.parse_expr_break()
            } else if this.eat_keyword(exp!(Yield)) {
                this.parse_expr_yield()
            } else if this.is_do_yeet() {
                this.parse_expr_yeet()
            } else if this.eat_keyword(exp!(Become)) {
                this.parse_expr_become()
            } else if this.check_keyword(exp!(Let)) {
                this.parse_expr_let(restrictions)
            } else if this.eat_keyword(exp!(Underscore)) {
                if let Some(expr) = this.maybe_recover_bad_struct_literal_path(true)? {
                    return Ok(expr);
                }
                Ok(this.mk_expr(this.prev_token.span, ExprKind::Underscore))
            } else if this.token_uninterpolated_span().at_least_rust_2018() {
                // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
                let at_async = this.check_keyword(exp!(Async));
                // check for `gen {}` and `gen move {}`
                // or `async gen {}` and `async gen move {}`
                // FIXME: (async) gen closures aren't yet parsed.
                // FIXME(gen_blocks): Parse `gen async` and suggest swap
                if this.token_uninterpolated_span().at_least_rust_2024()
                    && this.is_gen_block(kw::Gen, at_async as usize)
                {
                    this.parse_gen_block()
                // Check for `async {` and `async move {`,
                } else if this.is_gen_block(kw::Async, 0) {
                    this.parse_gen_block()
                } else if at_async {
                    this.parse_expr_closure()
                } else if this.eat_keyword_noexpect(kw::Await) {
                    this.recover_incorrect_await_syntax(lo)
                } else {
                    this.parse_expr_lit()
                }
            } else {
                this.parse_expr_lit()
            }
        })
    }

    fn parse_expr_lit(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;
        match self.parse_opt_token_lit() {
            Some((token_lit, _)) => {
                let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(token_lit));
                self.maybe_recover_from_bad_qpath(expr)
            }
            None => self.try_macro_suggestion(),
        }
    }

    fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;
        self.expect(exp!(OpenParen))?;
        let (es, trailing_comma) = match self.parse_seq_to_end(
            exp!(CloseParen),
            SeqSep::trailing_allowed(exp!(Comma)),
            |p| p.parse_expr_catch_underscore(restrictions.intersection(Restrictions::ALLOW_LET)),
        ) {
            Ok(x) => x,
            Err(err) => {
                return Ok(self.recover_seq_parse_error(
                    exp!(OpenParen),
                    exp!(CloseParen),
                    lo,
                    err,
                ));
            }
        };
        let kind = if es.len() == 1 && matches!(trailing_comma, Trailing::No) {
            // `(e)` is parenthesized `e`.
            ExprKind::Paren(es.into_iter().next().unwrap())
        } else {
            // `(e,)` is a tuple with only one field, `e`.
            ExprKind::Tup(es)
        };
        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;
        self.bump(); // `[` or other open delim

        let kind = if self.eat(close) {
            // Empty vector
            ExprKind::Array(ThinVec::new())
        } else {
            // Non-empty vector
            let first_expr = self.parse_expr()?;
            if self.eat(exp!(Semi)) {
                // Repeating array syntax: `[ 0; 512 ]`
                let count = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?;
                self.expect(close)?;
                ExprKind::Repeat(first_expr, count)
            } else if self.eat(exp!(Comma)) {
                // Vector with two or more elements.
                let sep = SeqSep::trailing_allowed(exp!(Comma));
                let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?;
                exprs.insert(0, first_expr);
                ExprKind::Array(exprs)
            } else {
                // Vector with one element
                self.expect(close)?;
                ExprKind::Array(thin_vec![first_expr])
            }
        };
        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    fn parse_expr_path_start(&mut self) -> PResult<'a, Box<Expr>> {
        let maybe_eq_tok = self.prev_token;
        let (qself, path) = if self.eat_lt() {
            let lt_span = self.prev_token.span;
            let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| {
                // Suggests using '<=' if there is an error parsing qpath when the previous token
                // is an '=' token. Only emits suggestion if the '<' token and '=' token are
                // directly adjacent (i.e. '=<')
                if maybe_eq_tok == TokenKind::Eq && maybe_eq_tok.span.hi() == lt_span.lo() {
                    let eq_lt = maybe_eq_tok.span.to(lt_span);
                    err.span_suggestion(eq_lt, "did you mean", "<=", Applicability::Unspecified);
                }
                err
            })?;
            (Some(qself), path)
        } else {
            (None, self.parse_path(PathStyle::Expr)?)
        };

        // `!`, as an operator, is prefix, so we know this isn't that.
        let (span, kind) = if self.eat(exp!(Bang)) {
            // MACRO INVOCATION expression
            if qself.is_some() {
                self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
            }
            let lo = path.span;
            let mac = Box::new(MacCall { path, args: self.parse_delim_args()? });
            (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
        } else if self.check(exp!(OpenBrace))
            && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
        {
            if qself.is_some() {
                self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
            }
            return expr;
        } else {
            (path.span, ExprKind::Path(qself, path))
        };

        let expr = self.mk_expr(span, kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `'label: $expr`. The label is already parsed.
    pub(super) fn parse_expr_labeled(
        &mut self,
        label_: Label,
        mut consume_colon: bool,
    ) -> PResult<'a, Box<Expr>> {
        let lo = label_.ident.span;
        let label = Some(label_);
        let ate_colon = self.eat(exp!(Colon));
        let tok_sp = self.token.span;
        let expr = if self.eat_keyword(exp!(While)) {
            self.parse_expr_while(label, lo)
        } else if self.eat_keyword(exp!(For)) {
            self.parse_expr_for(label, lo)
        } else if self.eat_keyword(exp!(Loop)) {
            self.parse_expr_loop(label, lo)
        } else if self.check_noexpect(&token::OpenBrace) || self.token.is_metavar_block() {
            self.parse_expr_block(label, lo, BlockCheckMode::Default)
        } else if !ate_colon
            && self.may_recover()
            && (self.token.kind.close_delim().is_some() || self.token.is_punct())
            && could_be_unclosed_char_literal(label_.ident)
        {
            let (lit, _) =
                self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
                    self_.dcx().create_err(errors::UnexpectedTokenAfterLabel {
                        span: self_.token.span,
                        remove_label: None,
                        enclose_in_block: None,
                    })
                });
            consume_colon = false;
            Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
        } else if !ate_colon
            && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
        {
            // We're probably inside of a `Path<'a>` that needs a turbofish
            let guar = self.dcx().emit_err(errors::UnexpectedTokenAfterLabel {
                span: self.token.span,
                remove_label: None,
                enclose_in_block: None,
            });
            consume_colon = false;
            Ok(self.mk_expr_err(lo, guar))
        } else {
            let mut err = errors::UnexpectedTokenAfterLabel {
                span: self.token.span,
                remove_label: None,
                enclose_in_block: None,
            };

            // Continue as an expression in an effort to recover on `'label: non_block_expr`.
            let expr = self.parse_expr().map(|expr| {
                let span = expr.span;

                let found_labeled_breaks = {
                    struct FindLabeledBreaksVisitor;

                    impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
                        type Result = ControlFlow<()>;
                        fn visit_expr(&mut self, ex: &'ast Expr) -> ControlFlow<()> {
                            if let ExprKind::Break(Some(_label), _) = ex.kind {
                                ControlFlow::Break(())
                            } else {
                                walk_expr(self, ex)
                            }
                        }
                    }

                    FindLabeledBreaksVisitor.visit_expr(&expr).is_break()
                };

                // Suggestion involves adding a labeled block.
                //
                // If there are no breaks that may use this label, suggest removing the label and
                // recover to the unmodified expression.
                if !found_labeled_breaks {
                    err.remove_label = Some(lo.until(span));

                    return expr;
                }

                err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
                    left: span.shrink_to_lo(),
                    right: span.shrink_to_hi(),
                });

                // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
                let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
                let blk = self.mk_block(thin_vec![stmt], BlockCheckMode::Default, span);
                self.mk_expr(span, ExprKind::Block(blk, label))
            });

            self.dcx().emit_err(err);
            expr
        }?;

        if !ate_colon && consume_colon {
            self.dcx().emit_err(errors::RequireColonAfterLabeledExpression {
                span: expr.span,
                label: lo,
                label_end: lo.between(tok_sp),
            });
        }

        Ok(expr)
    }

    /// Emit an error when a char is parsed as a lifetime or label because of a missing quote.
    pub(super) fn recover_unclosed_char<L>(
        &self,
        ident: Ident,
        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
        err: impl FnOnce(&Self) -> Diag<'a>,
    ) -> L {
        assert!(could_be_unclosed_char_literal(ident));
        self.dcx()
            .try_steal_modify_and_emit_err(ident.span, StashKey::LifetimeIsChar, |err| {
                err.span_suggestion_verbose(
                    ident.span.shrink_to_hi(),
                    "add `'` to close the char literal",
                    "'",
                    Applicability::MaybeIncorrect,
                );
            })
            .unwrap_or_else(|| {
                err(self)
                    .with_span_suggestion_verbose(
                        ident.span.shrink_to_hi(),
                        "add `'` to close the char literal",
                        "'",
                        Applicability::MaybeIncorrect,
                    )
                    .emit()
            });
        let name = ident.without_first_quote().name;
        mk_lit_char(name, ident.span)
    }

    /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
    fn recover_do_catch(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;

        self.bump(); // `do`
        self.bump(); // `catch`

        let span = lo.to(self.prev_token.span);
        self.dcx().emit_err(errors::DoCatchSyntaxRemoved { span });

        self.parse_try_block(lo)
    }

    /// Parse an expression if the token can begin one.
    fn parse_expr_opt(&mut self) -> PResult<'a, Option<Box<Expr>>> {
        Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None })
    }

    /// Parse `"return" expr?`.
    fn parse_expr_return(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.prev_token.span;
        let kind = ExprKind::Ret(self.parse_expr_opt()?);
        let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `"do" "yeet" expr?`.
    fn parse_expr_yeet(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;

        self.bump(); // `do`
        self.bump(); // `yeet`

        let kind = ExprKind::Yeet(self.parse_expr_opt()?);

        let span = lo.to(self.prev_token.span);
        self.psess.gated_spans.gate(sym::yeet_expr, span);
        let expr = self.mk_expr(span, kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `"become" expr`, with `"become"` token already eaten.
    fn parse_expr_become(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.prev_token.span;
        let kind = ExprKind::Become(self.parse_expr()?);
        let span = lo.to(self.prev_token.span);
        self.psess.gated_spans.gate(sym::explicit_tail_calls, span);
        let expr = self.mk_expr(span, kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `"break" (('label (:? expr)?) | expr?)` with `"break"` token already eaten.
    /// If the label is followed immediately by a `:` token, the label and `:` are
    /// parsed as part of the expression (i.e. a labeled loop). The language team has
    /// decided in #87026 to require parentheses as a visual aid to avoid confusion if
    /// the break expression of an unlabeled break is a labeled loop (as in
    /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
    /// expression only gets a warning for compatibility reasons; and a labeled break
    /// with a labeled loop does not even get a warning because there is no ambiguity.
    fn parse_expr_break(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.prev_token.span;
        let mut label = self.eat_label();
        let kind = if self.token == token::Colon
            && let Some(label) = label.take()
        {
            // The value expression can be a labeled loop, see issue #86948, e.g.:
            // `loop { break 'label: loop { break 'label 42; }; }`
            let lexpr = self.parse_expr_labeled(label, true)?;
            self.dcx().emit_err(errors::LabeledLoopInBreak {
                span: lexpr.span,
                sub: errors::WrapInParentheses::Expression {
                    left: lexpr.span.shrink_to_lo(),
                    right: lexpr.span.shrink_to_hi(),
                },
            });
            Some(lexpr)
        } else if self.token != token::OpenBrace
            || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
        {
            let mut expr = self.parse_expr_opt()?;
            if let Some(expr) = &mut expr {
                if label.is_some()
                    && match &expr.kind {
                        ExprKind::While(_, _, None)
                        | ExprKind::ForLoop { label: None, .. }
                        | ExprKind::Loop(_, None, _) => true,
                        ExprKind::Block(block, None) => {
                            matches!(block.rules, BlockCheckMode::Default)
                        }
                        _ => false,
                    }
                {
                    let span = expr.span;
                    self.psess.buffer_lint(
                        BREAK_WITH_LABEL_AND_LOOP,
                        lo.to(expr.span),
                        ast::CRATE_NODE_ID,
                        errors::BreakWithLabelAndLoop {
                            sub: errors::BreakWithLabelAndLoopSub {
                                left: span.shrink_to_lo(),
                                right: span.shrink_to_hi(),
                            },
                        },
                    );
                }

                // Recover `break label aaaaa`
                if self.may_recover()
                    && let ExprKind::Path(None, p) = &expr.kind
                    && let [segment] = &*p.segments
                    && let &ast::PathSegment { ident, args: None, .. } = segment
                    && let Some(next) = self.parse_expr_opt()?
                {
                    label = Some(self.recover_ident_into_label(ident));
                    *expr = next;
                }
            }

            expr
        } else {
            None
        };
        let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind));
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `"continue" label?`.
    fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
        let mut label = self.eat_label();

        // Recover `continue label` -> `continue 'label`
        if self.may_recover()
            && label.is_none()
            && let Some((ident, _)) = self.token.ident()
        {
            self.bump();
            label = Some(self.recover_ident_into_label(ident));
        }

        let kind = ExprKind::Continue(label);
        Ok(self.mk_expr(lo.to(self.prev_token.span), kind))
    }

    /// Parse `"yield" expr?`.
    fn parse_expr_yield(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.prev_token.span;
        let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?));
        let span = lo.to(self.prev_token.span);
        self.psess.gated_spans.gate(sym::yield_expr, span);
        let expr = self.mk_expr(span, kind);
        self.maybe_recover_from_bad_qpath(expr)
    }

    /// Parse `builtin # ident(args,*)`.
    fn parse_expr_builtin(&mut self) -> PResult<'a, Box<Expr>> {
        self.parse_builtin(|this, lo, ident| {
            Ok(match ident.name {
                sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
                sym::type_ascribe => Some(this.parse_expr_type_ascribe(lo)?),
                sym::wrap_binder => {
                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Wrap)?)
                }
                sym::unwrap_binder => {
                    Some(this.parse_expr_unsafe_binder_cast(lo, UnsafeBinderCastKind::Unwrap)?)
                }
                _ => None,
            })
        })
    }

    pub(crate) fn parse_builtin<T>(
        &mut self,
        parse: impl FnOnce(&mut Parser<'a>, Span, Ident) -> PResult<'a, Option<T>>,
    ) -> PResult<'a, T> {
        let lo = self.token.span;

        self.bump(); // `builtin`
        self.bump(); // `#`

        let Some((ident, IdentIsRaw::No)) = self.token.ident() else {
            let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span });
            return Err(err);
        };
        self.psess.gated_spans.gate(sym::builtin_syntax, ident.span);
        self.bump();

        self.expect(exp!(OpenParen))?;
        let ret = if let Some(res) = parse(self, lo, ident)? {
            Ok(res)
        } else {
            let err = self.dcx().create_err(errors::UnknownBuiltinConstruct {
                span: lo.to(ident.span),
                name: ident,
            });
            return Err(err);
        };
        self.expect(exp!(CloseParen))?;

        ret
    }

    /// Built-in macro for `offset_of!` expressions.
    pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
        let container = self.parse_ty()?;
        self.expect(exp!(Comma))?;

        let fields = self.parse_floating_field_access()?;
        let trailing_comma = self.eat_noexpect(&TokenKind::Comma);

        if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {
            if trailing_comma {
                e.note("unexpected third argument to offset_of");
            } else {
                e.note("offset_of expects dot-separated field and variant names");
            }
            e.emit();
        }

        // Eat tokens until the macro call ends.
        if self.may_recover() {
            while !self.token.kind.is_close_delim_or_eof() {
                self.bump();
            }
        }

        let span = lo.to(self.token.span);
        Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields)))
    }

    /// Built-in macro for type ascription expressions.
    pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
        let expr = self.parse_expr()?;
        self.expect(exp!(Comma))?;
        let ty = self.parse_ty()?;
        let span = lo.to(self.token.span);
        Ok(self.mk_expr(span, ExprKind::Type(expr, ty)))
    }

    pub(crate) fn parse_expr_unsafe_binder_cast(
        &mut self,
        lo: Span,
        kind: UnsafeBinderCastKind,
    ) -> PResult<'a, Box<Expr>> {
        let expr = self.parse_expr()?;
        let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None };
        let span = lo.to(self.token.span);
        Ok(self.mk_expr(span, ExprKind::UnsafeBinderCast(kind, expr, ty)))
    }

    /// Returns a string literal if the next token is a string literal.
    /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
    /// and returns `None` if the next token is not literal at all.
    pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<MetaItemLit>> {
        match self.parse_opt_meta_item_lit() {
            Some(lit) => match lit.kind {
                ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
                    style,
                    symbol: lit.symbol,
                    suffix: lit.suffix,
                    span: lit.span,
                    symbol_unescaped,
                }),
                _ => Err(Some(lit)),
            },
            None => Err(None),
        }
    }

    pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) {
        (token::Lit { symbol: name, suffix: None, kind: token::Char }, span)
    }

    fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit {
        ast::MetaItemLit {
            symbol: name,
            suffix: None,
            kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')),
            span,
        }
    }

    fn handle_missing_lit<L>(
        &mut self,
        mk_lit_char: impl FnOnce(Symbol, Span) -> L,
    ) -> PResult<'a, L> {
        let token = self.token;
        let err = |self_: &Self| {
            let msg = format!("unexpected token: {}", super::token_descr(&token));
            self_.dcx().struct_span_err(token.span, msg)
        };
        // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
        // makes sense.
        if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
            && could_be_unclosed_char_literal(ident)
        {
            let lt = self.expect_lifetime();
            Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err))
        } else {
            Err(err(self))
        }
    }

    pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> {
        self.parse_opt_token_lit()
            .ok_or(())
            .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char))
    }

    pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> {
        self.parse_opt_meta_item_lit()
            .ok_or(())
            .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char))
    }

    fn recover_after_dot(&mut self) {
        if self.token == token::Dot {
            // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
            // dot would follow an optional literal, so we do this unconditionally.
            let recovered = self.look_ahead(1, |next_token| {
                // If it's an integer that looks like a float, then recover as such.
                //
                // We will never encounter the exponent part of a floating
                // point literal here, since there's no use of the exponent
                // syntax that also constitutes a valid integer, so we need
                // not check for that.
                if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
                    next_token.kind
                    && suffix.is_none_or(|s| s == sym::f32 || s == sym::f64)
                    && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
                    && self.token.span.hi() == next_token.span.lo()
                {
                    let s = String::from("0.") + symbol.as_str();
                    let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
                    Some(Token::new(kind, self.token.span.to(next_token.span)))
                } else {
                    None
                }
            });
            if let Some(recovered) = recovered {
                self.dcx().emit_err(errors::FloatLiteralRequiresIntegerPart {
                    span: recovered.span,
                    suggestion: recovered.span.shrink_to_lo(),
                });
                self.bump();
                self.token = recovered;
            }
        }
    }

    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
    /// `Lit::from_token` (excluding unary negation).
    pub fn eat_token_lit(&mut self) -> Option<token::Lit> {
        let check_expr = |expr: Box<Expr>| {
            if let ast::ExprKind::Lit(token_lit) = expr.kind {
                Some(token_lit)
            } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
                && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
            {
                None
            } else {
                panic!("unexpected reparsed expr/literal: {:?}", expr.kind);
            }
        };
        match self.token.uninterpolate().kind {
            token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => {
                self.bump();
                Some(token::Lit::new(token::Bool, name, None))
            }
            token::Literal(token_lit) => {
                self.bump();
                Some(token_lit)
            }
            token::OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Literal)) => {
                let lit = self
                    .eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
                    .expect("metavar seq literal");
                check_expr(lit)
            }
            token::OpenInvisible(InvisibleOrigin::MetaVar(
                mv_kind @ MetaVarKind::Expr { can_begin_literal_maybe_minus: true, .. },
            )) => {
                let expr = self
                    .eat_metavar_seq(mv_kind, |this| this.parse_expr())
                    .expect("metavar seq expr");
                check_expr(expr)
            }
            _ => None,
        }
    }

    /// Matches `lit = true | false | token_lit`.
    /// Returns `None` if the next token is not a literal.
    fn parse_opt_token_lit(&mut self) -> Option<(token::Lit, Span)> {
        self.recover_after_dot();
        let span = self.token.span;
        self.eat_token_lit().map(|token_lit| (token_lit, span))
    }

    /// Matches `lit = true | false | token_lit`.
    /// Returns `None` if the next token is not a literal.
    fn parse_opt_meta_item_lit(&mut self) -> Option<MetaItemLit> {
        self.recover_after_dot();
        let span = self.token.span;
        let uninterpolated_span = self.token_uninterpolated_span();
        self.eat_token_lit().map(|token_lit| {
            match MetaItemLit::from_token_lit(token_lit, span) {
                Ok(lit) => lit,
                Err(err) => {
                    let guar = report_lit_error(&self.psess, err, token_lit, uninterpolated_span);
                    // Pack possible quotes and prefixes from the original literal into
                    // the error literal's symbol so they can be pretty-printed faithfully.
                    let suffixless_lit = token::Lit::new(token_lit.kind, token_lit.symbol, None);
                    let symbol = Symbol::intern(&suffixless_lit.to_string());
                    let token_lit = token::Lit::new(token::Err(guar), symbol, token_lit.suffix);
                    MetaItemLit::from_token_lit(token_lit, uninterpolated_span).unwrap()
                }
            }
        })
    }

    /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
    /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
    pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> {
        if let Some(expr) = self.eat_metavar_seq_with_matcher(
            |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
            |this| {
                // FIXME(nnethercote) The `expr` case should only match if
                // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
                // an `UnOp::Neg` and an `ExprKind::Lit`, like how
                // `can_begin_literal_maybe_minus` works. But this method has
                // been over-accepting for a long time, and to make that change
                // here requires also changing some `parse_literal_maybe_minus`
                // call sites to accept additional expression kinds. E.g.
                // `ExprKind::Path` must be accepted when parsing range
                // patterns. That requires some care. So for now, we continue
                // being less strict here than we should be.
                this.parse_expr()
            },
        ) {
            return Ok(expr);
        } else if let Some(lit) =
            self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus())
        {
            return Ok(lit);
        }

        let lo = self.token.span;
        let minus_present = self.eat(exp!(Minus));
        let (token_lit, span) = self.parse_token_lit()?;
        let expr = self.mk_expr(span, ExprKind::Lit(token_lit));

        if minus_present {
            Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_unary(UnOp::Neg, expr)))
        } else {
            Ok(expr)
        }
    }

    fn is_array_like_block(&mut self) -> bool {
        self.token.kind == TokenKind::OpenBrace
            && self
                .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
            && self.look_ahead(2, |t| t == &token::Comma)
            && self.look_ahead(3, |t| t.can_begin_expr())
    }

    /// Emits a suggestion if it looks like the user meant an array but
    /// accidentally used braces, causing the code to be interpreted as a block
    /// expression.
    fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<Box<Expr>> {
        let mut snapshot = self.create_snapshot_for_diagnostic();
        match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
            Ok(arr) => {
                let guar = self.dcx().emit_err(errors::ArrayBracketsInsteadOfBraces {
                    span: arr.span,
                    sub: errors::ArrayBracketsInsteadOfBracesSugg {
                        left: lo,
                        right: snapshot.prev_token.span,
                    },
                });

                self.restore_snapshot(snapshot);
                Some(self.mk_expr_err(arr.span, guar))
            }
            Err(e) => {
                e.cancel();
                None
            }
        }
    }

    fn suggest_missing_semicolon_before_array(
        &self,
        prev_span: Span,
        open_delim_span: Span,
    ) -> PResult<'a, ()> {
        if !self.may_recover() {
            return Ok(());
        }

        if self.token == token::Comma {
            if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) {
                return Ok(());
            }
            let mut snapshot = self.create_snapshot_for_diagnostic();
            snapshot.bump();
            match snapshot.parse_seq_to_before_end(
                exp!(CloseBracket),
                SeqSep::trailing_allowed(exp!(Comma)),
                |p| p.parse_expr(),
            ) {
                Ok(_)
                    // When the close delim is `)`, `token.kind` is expected to be `token::CloseParen`,
                    // but the actual `token.kind` is `token::CloseBracket`.
                    // This is because the `token.kind` of the close delim is treated as the same as
                    // that of the open delim in `TokenTreesReader::parse_token_tree`, even if the delimiters of them are different.
                    // Therefore, `token.kind` should not be compared here.
                    if snapshot
                        .span_to_snippet(snapshot.token.span)
                        .is_ok_and(|snippet| snippet == "]") =>
                {
                    return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray {
                        open_delim: open_delim_span,
                        semicolon: prev_span.shrink_to_hi(),
                    }));
                }
                Ok(_) => (),
                Err(err) => err.cancel(),
            }
        }
        Ok(())
    }

    /// Parses a block or unsafe block.
    pub(super) fn parse_expr_block(
        &mut self,
        opt_label: Option<Label>,
        lo: Span,
        blk_mode: BlockCheckMode,
    ) -> PResult<'a, Box<Expr>> {
        if self.may_recover() && self.is_array_like_block() {
            if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
                return Ok(arr);
            }
        }

        if self.token.is_metavar_block() {
            self.dcx().emit_err(errors::InvalidBlockMacroSegment {
                span: self.token.span,
                context: lo.to(self.token.span),
                wrap: errors::WrapInExplicitBlock {
                    lo: self.token.span.shrink_to_lo(),
                    hi: self.token.span.shrink_to_hi(),
                },
            });
        }

        let (attrs, blk) = self.parse_block_common(lo, blk_mode, None)?;
        Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs))
    }

    /// Parse a block which takes no attributes and has no label
    fn parse_simple_block(&mut self) -> PResult<'a, Box<Expr>> {
        let blk = self.parse_block()?;
        Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
    }

    /// Parses a closure expression (e.g., `move |args| expr`).
    fn parse_expr_closure(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;

        let before = self.prev_token;
        let binder = if self.check_keyword(exp!(For)) {
            let lo = self.token.span;
            let (bound_vars, _) = self.parse_higher_ranked_binder()?;
            let span = lo.to(self.prev_token.span);

            self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);

            ClosureBinder::For { span, generic_params: bound_vars }
        } else {
            ClosureBinder::NotPresent
        };

        let constness = self.parse_closure_constness();

        let movability = if self.eat_keyword(exp!(Static)) {
            self.psess.gated_spans.gate(sym::coroutines, self.prev_token.span);
            Movability::Static
        } else {
            Movability::Movable
        };

        let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() {
            self.parse_coroutine_kind(Case::Sensitive)
        } else {
            None
        };

        if let ClosureBinder::NotPresent = binder
            && coroutine_kind.is_some()
        {
            // coroutine closures and generators can have the same qualifiers, so we might end up
            // in here if there is a missing `|` but also no `{`. Adjust the expectations in that case.
            self.expected_token_types.insert(TokenType::OpenBrace);
        }

        let capture_clause = self.parse_capture_clause()?;
        let (fn_decl, fn_arg_span) = self.parse_fn_block_decl()?;
        let decl_hi = self.prev_token.span;
        let mut body = match &fn_decl.output {
            // No return type.
            FnRetTy::Default(_) => {
                let restrictions =
                    self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
                let prev = self.prev_token;
                let token = self.token;
                let attrs = self.parse_outer_attributes()?;
                match self.parse_expr_res(restrictions, attrs) {
                    Ok((expr, _)) => expr,
                    Err(err) => self.recover_closure_body(err, before, prev, token, lo, decl_hi)?,
                }
            }
            // Explicit return type (`->`) needs block `-> T { }`.
            FnRetTy::Ty(ty) => self.parse_closure_block_body(ty.span)?,
        };

        match coroutine_kind {
            Some(CoroutineKind::Async { .. }) => {}
            Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
                // Feature-gate `gen ||` and `async gen ||` closures.
                // FIXME(gen_blocks): This perhaps should be a different gate.
                self.psess.gated_spans.gate(sym::gen_blocks, span);
            }
            None => {}
        }

        if self.token == TokenKind::Semi
            && let Some(last) = self.token_cursor.stack.last()
            && let Some(TokenTree::Delimited(_, _, Delimiter::Parenthesis, _)) = last.curr()
            && self.may_recover()
        {
            // It is likely that the closure body is a block but where the
            // braces have been removed. We will recover and eat the next
            // statements later in the parsing process.
            body = self.mk_expr_err(
                body.span,
                self.dcx().span_delayed_bug(body.span, "recovered a closure body as a block"),
            );
        }

        let body_span = body.span;

        let closure = self.mk_expr(
            lo.to(body.span),
            ExprKind::Closure(Box::new(ast::Closure {
                binder,
                capture_clause,
                constness,
                coroutine_kind,
                movability,
                fn_decl,
                body,
                fn_decl_span: lo.to(decl_hi),
                fn_arg_span,
            })),
        );

        // Disable recovery for closure body
        let spans =
            ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
        self.current_closure = Some(spans);

        Ok(closure)
    }

    /// If an explicit return type is given, require a block to appear (RFC 968).
    fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, Box<Expr>> {
        if self.may_recover()
            && self.token.can_begin_expr()
            && self.token.kind != TokenKind::OpenBrace
            && !self.token.is_metavar_block()
        {
            let snapshot = self.create_snapshot_for_diagnostic();
            let restrictions =
                self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET;
            let tok = self.token.clone();
            match self.parse_expr_res(restrictions, AttrWrapper::empty()) {
                Ok((expr, _)) => {
                    let descr = super::token_descr(&tok);
                    let mut diag = self
                        .dcx()
                        .struct_span_err(tok.span, format!("expected `{{`, found {descr}"));
                    diag.span_label(
                        ret_span,
                        "explicit return type requires closure body to be enclosed in braces",
                    );
                    diag.multipart_suggestion(
                        "wrap the expression in curly braces",
                        vec![
                            (expr.span.shrink_to_lo(), "{ ".to_string()),
                            (expr.span.shrink_to_hi(), " }".to_string()),
                        ],
                        Applicability::MachineApplicable,
                    );
                    diag.emit();
                    return Ok(expr);
                }
                Err(diag) => {
                    diag.cancel();
                    self.restore_snapshot(snapshot);
                }
            }
        }

        let body_lo = self.token.span;
        self.parse_expr_block(None, body_lo, BlockCheckMode::Default)
    }

    /// Parses an optional `move` or `use` prefix to a closure-like construct.
    fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
        if self.eat_keyword(exp!(Move)) {
            let move_kw_span = self.prev_token.span;
            // Check for `move async` and recover
            if self.check_keyword(exp!(Async)) {
                let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
                Err(self
                    .dcx()
                    .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span }))
            } else {
                Ok(CaptureBy::Value { move_kw: move_kw_span })
            }
        } else if self.eat_keyword(exp!(Use)) {
            let use_kw_span = self.prev_token.span;
            self.psess.gated_spans.gate(sym::ergonomic_clones, use_kw_span);
            // Check for `use async` and recover
            if self.check_keyword(exp!(Async)) {
                let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
                Err(self.dcx().create_err(errors::AsyncUseOrderIncorrect { span: use_async_span }))
            } else {
                Ok(CaptureBy::Use { use_kw: use_kw_span })
            }
        } else {
            Ok(CaptureBy::Ref)
        }
    }

    /// Parses the `|arg, arg|` header of a closure.
    fn parse_fn_block_decl(&mut self) -> PResult<'a, (Box<FnDecl>, Span)> {
        let arg_start = self.token.span.lo();

        let inputs = if self.eat(exp!(OrOr)) {
            ThinVec::new()
        } else {
            self.expect(exp!(Or))?;
            let args = self
                .parse_seq_to_before_tokens(
                    &[exp!(Or)],
                    &[&token::OrOr],
                    SeqSep::trailing_allowed(exp!(Comma)),
                    |p| p.parse_fn_block_param(),
                )?
                .0;
            self.expect_or()?;
            args
        };
        let arg_span = self.prev_token.span.with_lo(arg_start);
        let output =
            self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?;

        Ok((Box::new(FnDecl { inputs, output }), arg_span))
    }

    /// Parses a parameter in a closure header (e.g., `|arg, arg|`).
    fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
        let lo = self.token.span;
        let attrs = self.parse_outer_attributes()?;
        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let pat = Box::new(this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?);
            let ty = if this.eat(exp!(Colon)) {
                this.parse_ty()?
            } else {
                this.mk_ty(pat.span, TyKind::Infer)
            };

            Ok((
                Param {
                    attrs,
                    ty,
                    pat,
                    span: lo.to(this.prev_token.span),
                    id: DUMMY_NODE_ID,
                    is_placeholder: false,
                },
                Trailing::from(this.token == token::Comma),
                UsePreAttrPos::No,
            ))
        })
    }

    /// Parses an `if` expression (`if` token already eaten).
    fn parse_expr_if(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.prev_token.span;
        // Scoping code checks the top level edition of the `if`; let's match it here.
        // The `CondChecker` also checks the edition of the `let` itself, just to make sure.
        let let_chains_policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
        let cond = self.parse_expr_cond(let_chains_policy)?;
        self.parse_if_after_cond(lo, cond)
    }

    fn parse_if_after_cond(&mut self, lo: Span, mut cond: Box<Expr>) -> PResult<'a, Box<Expr>> {
        let cond_span = cond.span;
        // Tries to interpret `cond` as either a missing expression if it's a block,
        // or as an unfinished expression if it's a binop and the RHS is a block.
        // We could probably add more recoveries here too...
        let mut recover_block_from_condition = |this: &mut Self| {
            let block = match &mut cond.kind {
                ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
                    if let ExprKind::Block(_, None) = right.kind =>
                {
                    let guar = this.dcx().emit_err(errors::IfExpressionMissingThenBlock {
                        if_span: lo,
                        missing_then_block_sub:
                            errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(
                                cond_span.shrink_to_lo().to(*binop_span),
                            ),
                        let_else_sub: None,
                    });
                    std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi(), guar))
                }
                ExprKind::Block(_, None) => {
                    let guar = this.dcx().emit_err(errors::IfExpressionMissingCondition {
                        if_span: lo.with_neighbor(cond.span).shrink_to_hi(),
                        block_span: self.psess.source_map().start_point(cond_span),
                    });
                    std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar))
                }
                _ => {
                    return None;
                }
            };
            if let ExprKind::Block(block, _) = &block.kind {
                Some(block.clone())
            } else {
                unreachable!()
            }
        };
        // Parse then block
        let thn = if self.token.is_keyword(kw::Else) {
            if let Some(block) = recover_block_from_condition(self) {
                block
            } else {
                let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
                    .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });

                let guar = self.dcx().emit_err(errors::IfExpressionMissingThenBlock {
                    if_span: lo,
                    missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
                        cond_span.shrink_to_hi(),
                    ),
                    let_else_sub,
                });
                self.mk_block_err(cond_span.shrink_to_hi(), guar)
            }
        } else {
            let attrs = self.parse_outer_attributes()?; // For recovery.
            let maybe_fatarrow = self.token;
            let block = if self.check(exp!(OpenBrace)) {
                self.parse_block()?
            } else if let Some(block) = recover_block_from_condition(self) {
                block
            } else {
                self.error_on_extra_if(&cond)?;
                // Parse block, which will always fail, but we can add a nice note to the error
                self.parse_block().map_err(|mut err| {
                        if self.prev_token == token::Semi
                            && self.token == token::AndAnd
                            && let maybe_let = self.look_ahead(1, |t| t.clone())
                            && maybe_let.is_keyword(kw::Let)
                        {
                            err.span_suggestion(
                                self.prev_token.span,
                                "consider removing this semicolon to parse the `let` as part of the same chain",
                                "",
                                Applicability::MachineApplicable,
                            ).span_note(
                                self.token.span.to(maybe_let.span),
                                "you likely meant to continue parsing the let-chain starting here",
                            );
                        } else {
                            // Look for usages of '=>' where '>=' might be intended
                            if maybe_fatarrow == token::FatArrow {
                                err.span_suggestion(
                                    maybe_fatarrow.span,
                                    "you might have meant to write a \"greater than or equal to\" comparison",
                                    ">=",
                                    Applicability::MaybeIncorrect,
                                );
                            }
                            err.span_note(
                                cond_span,
                                "the `if` expression is missing a block after this condition",
                            );
                        }
                        err
                    })?
            };
            self.error_on_if_block_attrs(lo, false, block.span, attrs);
            block
        };
        let els = if self.eat_keyword(exp!(Else)) { Some(self.parse_expr_else()?) } else { None };
        Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
    }

    /// Parses the condition of a `if` or `while` expression.
    ///
    /// The specified `edition` in `let_chains_policy` should be that of the whole `if` construct,
    /// i.e. the same span we use to later decide whether the drop behaviour should be that of
    /// edition `..=2021` or that of `2024..`.
    // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt
    pub fn parse_expr_cond(
        &mut self,
        let_chains_policy: LetChainsPolicy,
    ) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        let (mut cond, _) =
            self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;

        let mut checker = CondChecker::new(self, let_chains_policy);
        checker.visit_expr(&mut cond);
        Ok(if let Some(guar) = checker.found_incorrect_let_chain {
            self.mk_expr_err(cond.span, guar)
        } else {
            cond
        })
    }

    /// Parses a `let $pat = $expr` pseudo-expression.
    fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
        let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
            let err = errors::ExpectedExpressionFoundLet {
                span: self.token.span,
                reason: errors::ForbiddenLetReason::OtherForbidden,
                missing_let: None,
                comparison: None,
            };
            if self.prev_token == token::Or {
                // This was part of a closure, the that part of the parser recover.
                return Err(self.dcx().create_err(err));
            } else {
                Recovered::Yes(self.dcx().emit_err(err))
            }
        } else {
            Recovered::No
        };
        self.bump(); // Eat `let` token
        let lo = self.prev_token.span;
        let pat = self.parse_pat_no_top_guard(
            None,
            RecoverComma::Yes,
            RecoverColon::Yes,
            CommaRecoveryMode::LikelyTuple,
        )?;
        if self.token == token::EqEq {
            self.dcx().emit_err(errors::ExpectedEqForLetExpr {
                span: self.token.span,
                sugg_span: self.token.span,
            });
            self.bump();
        } else {
            self.expect(exp!(Eq))?;
        }
        let attrs = self.parse_outer_attributes()?;
        let (expr, _) =
            self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?;
        let span = lo.to(expr.span);
        Ok(self.mk_expr(span, ExprKind::Let(Box::new(pat), expr, span, recovered)))
    }

    /// Parses an `else { ... }` expression (`else` token already eaten).
    fn parse_expr_else(&mut self) -> PResult<'a, Box<Expr>> {
        let else_span = self.prev_token.span; // `else`
        let attrs = self.parse_outer_attributes()?; // For recovery.
        let expr = if self.eat_keyword(exp!(If)) {
            ensure_sufficient_stack(|| self.parse_expr_if())?
        } else if self.check(exp!(OpenBrace)) {
            self.parse_simple_block()?
        } else {
            let snapshot = self.create_snapshot_for_diagnostic();
            let first_tok = super::token_descr(&self.token);
            let first_tok_span = self.token.span;
            match self.parse_expr() {
                Ok(cond)
                // Try to guess the difference between a "condition-like" vs
                // "statement-like" expression.
                //
                // We are seeing the following code, in which $cond is neither
                // ExprKind::Block nor ExprKind::If (the 2 cases wherein this
                // would be valid syntax).
                //
                //     if ... {
                //     } else $cond
                //
                // If $cond is "condition-like" such as ExprKind::Binary, we
                // want to suggest inserting `if`.
                //
                //     if ... {
                //     } else if a == b {
                //            ^^
                //     }
                //
                // We account for macro calls that were meant as conditions as well.
                //
                //     if ... {
                //     } else if macro! { foo bar } {
                //            ^^
                //     }
                //
                // If $cond is "statement-like" such as ExprKind::While then we
                // want to suggest wrapping in braces.
                //
                //     if ... {
                //     } else {
                //            ^
                //         while true {}
                //     }
                //     ^
                    if self.check(exp!(OpenBrace))
                        && (classify::expr_requires_semi_to_be_stmt(&cond)
                            || matches!(cond.kind, ExprKind::MacCall(..)))
                    =>
                {
                    self.dcx().emit_err(errors::ExpectedElseBlock {
                        first_tok_span,
                        first_tok,
                        else_span,
                        condition_start: cond.span.shrink_to_lo(),
                    });
                    self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
                }
                Err(e) => {
                    e.cancel();
                    self.restore_snapshot(snapshot);
                    self.parse_simple_block()?
                },
                Ok(_) => {
                    self.restore_snapshot(snapshot);
                    self.parse_simple_block()?
                },
            }
        };
        self.error_on_if_block_attrs(else_span, true, expr.span, attrs);
        Ok(expr)
    }

    fn error_on_if_block_attrs(
        &self,
        ctx_span: Span,
        is_ctx_else: bool,
        branch_span: Span,
        attrs: AttrWrapper,
    ) {
        if !attrs.is_empty()
            && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess)
        {
            let attributes = x0.span.until(branch_span);
            let last = xn.span;
            let ctx = if is_ctx_else { "else" } else { "if" };
            self.dcx().emit_err(errors::OuterAttributeNotAllowedOnIfElse {
                last,
                branch_span,
                ctx_span,
                ctx: ctx.to_string(),
                attributes,
            });
        }
    }

    fn error_on_extra_if(&mut self, cond: &Box<Expr>) -> PResult<'a, ()> {
        if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind
            && let BinOpKind::And = binop
            && let ExprKind::If(cond, ..) = &right.kind
        {
            Err(self.dcx().create_err(errors::UnexpectedIfWithIf(
                binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()),
            )))
        } else {
            Ok(())
        }
    }

    // Public to use it for custom `for` expressions in rustfmt forks like https://github.com/tucant/rustfmt
    pub fn parse_for_head(&mut self) -> PResult<'a, (Pat, Box<Expr>)> {
        let begin_paren = if self.token == token::OpenParen {
            // Record whether we are about to parse `for (`.
            // This is used below for recovery in case of `for ( $stuff ) $block`
            // in which case we will suggest `for $stuff $block`.
            let start_span = self.token.span;
            let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
            Some((start_span, left))
        } else {
            None
        };
        // Try to parse the pattern `for ($PAT) in $EXPR`.
        let pat = match (
            self.parse_pat_allow_top_guard(
                None,
                RecoverComma::Yes,
                RecoverColon::Yes,
                CommaRecoveryMode::LikelyTuple,
            ),
            begin_paren,
        ) {
            (Ok(pat), _) => pat, // Happy path.
            (Err(err), Some((start_span, left))) if self.eat_keyword(exp!(In)) => {
                // We know for sure we have seen `for ($SOMETHING in`. In the happy path this would
                // happen right before the return of this method.
                let attrs = self.parse_outer_attributes()?;
                let (expr, _) = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs) {
                    Ok(expr) => expr,
                    Err(expr_err) => {
                        // We don't know what followed the `in`, so cancel and bubble up the
                        // original error.
                        expr_err.cancel();
                        return Err(err);
                    }
                };
                return if self.token == token::CloseParen {
                    // We know for sure we have seen `for ($SOMETHING in $EXPR)`, so we recover the
                    // parser state and emit a targeted suggestion.
                    let span = vec![start_span, self.token.span];
                    let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
                    self.bump(); // )
                    err.cancel();
                    self.dcx().emit_err(errors::ParenthesesInForHead {
                        span,
                        // With e.g. `for (x) in y)` this would replace `(x) in y)`
                        // with `x) in y)` which is syntactically invalid.
                        // However, this is prevented before we get here.
                        sugg: errors::ParenthesesInForHeadSugg { left, right },
                    });
                    Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr))
                } else {
                    Err(err) // Some other error, bubble up.
                };
            }
            (Err(err), _) => return Err(err), // Some other error, bubble up.
        };
        if !self.eat_keyword(exp!(In)) {
            self.error_missing_in_for_loop();
        }
        self.check_for_for_in_in_typo(self.prev_token.span);
        let attrs = self.parse_outer_attributes()?;
        let (expr, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
        Ok((pat, expr))
    }

    /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
        let is_await =
            self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));

        if is_await {
            self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
        }

        let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For };

        let (pat, expr) = self.parse_for_head()?;
        let pat = Box::new(pat);
        // Recover from missing expression in `for` loop
        if matches!(expr.kind, ExprKind::Block(..))
            && self.token.kind != token::OpenBrace
            && self.may_recover()
        {
            let guar = self
                .dcx()
                .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
            let err_expr = self.mk_expr(expr.span, ExprKind::Err(guar));
            let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span);
            return Ok(self.mk_expr(
                lo.to(self.prev_token.span),
                ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, kind },
            ));
        }

        let (attrs, loop_block) = self.parse_inner_attrs_and_block(
            // Only suggest moving erroneous block label to the loop header
            // if there is not already a label there
            opt_label.is_none().then_some(lo),
        )?;

        let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind };

        self.recover_loop_else("for", lo)?;

        Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
    }

    /// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
    fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
        if self.token.is_keyword(kw::Else) && self.may_recover() {
            let else_span = self.token.span;
            self.bump();
            let else_clause = self.parse_expr_else()?;
            self.dcx().emit_err(errors::LoopElseNotSupported {
                span: else_span.to(else_clause.span),
                loop_kind,
                loop_kw,
            });
        }
        Ok(())
    }

    fn error_missing_in_for_loop(&mut self) {
        let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
            // Possibly using JS syntax (#75311).
            let span = self.token.span;
            self.bump();
            (span, errors::MissingInInForLoopSub::InNotOf)
        } else if self.eat(exp!(Eq)) {
            (self.prev_token.span, errors::MissingInInForLoopSub::InNotEq)
        } else {
            (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
        };

        self.dcx().emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
    }

    /// Parses a `while` or `while let` expression (`while` token already eaten).
    fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
        let policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
        let cond = self.parse_expr_cond(policy).map_err(|mut err| {
            err.span_label(lo, "while parsing the condition of this `while` expression");
            err
        })?;
        let (attrs, body) = self
            .parse_inner_attrs_and_block(
                // Only suggest moving erroneous block label to the loop header
                // if there is not already a label there
                opt_label.is_none().then_some(lo),
            )
            .map_err(|mut err| {
                err.span_label(lo, "while parsing the body of this `while` expression");
                err.span_label(cond.span, "this `while` condition successfully parsed");
                err
            })?;

        self.recover_loop_else("while", lo)?;

        Ok(self.mk_expr_with_attrs(
            lo.to(self.prev_token.span),
            ExprKind::While(cond, body, opt_label),
            attrs,
        ))
    }

    /// Parses `loop { ... }` (`loop` token already eaten).
    fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
        let loop_span = self.prev_token.span;
        let (attrs, body) = self.parse_inner_attrs_and_block(
            // Only suggest moving erroneous block label to the loop header
            // if there is not already a label there
            opt_label.is_none().then_some(lo),
        )?;
        self.recover_loop_else("loop", lo)?;
        Ok(self.mk_expr_with_attrs(
            lo.to(self.prev_token.span),
            ExprKind::Loop(body, opt_label, loop_span),
            attrs,
        ))
    }

    pub(crate) fn eat_label(&mut self) -> Option<Label> {
        if let Some((ident, is_raw)) = self.token.lifetime() {
            // Disallow `'fn`, but with a better error message than `expect_lifetime`.
            if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved() {
                self.dcx().emit_err(errors::KeywordLabel { span: ident.span });
            }

            self.bump();
            Some(Label { ident })
        } else {
            None
        }
    }

    /// Parses a `match ... { ... }` expression (`match` token already eaten).
    fn parse_expr_match(&mut self) -> PResult<'a, Box<Expr>> {
        let match_span = self.prev_token.span;
        let attrs = self.parse_outer_attributes()?;
        let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;

        self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix)
    }

    /// Parses the block of a `match expr { ... }` or a `expr.match { ... }`
    /// expression. This is after the match token and scrutinee are eaten
    fn parse_match_block(
        &mut self,
        lo: Span,
        match_span: Span,
        scrutinee: Box<Expr>,
        match_kind: MatchKind,
    ) -> PResult<'a, Box<Expr>> {
        if let Err(mut e) = self.expect(exp!(OpenBrace)) {
            if self.token == token::Semi {
                e.span_suggestion_short(
                    match_span,
                    "try removing this `match`",
                    "",
                    Applicability::MaybeIncorrect, // speculative
                );
            }
            if self.maybe_recover_unexpected_block_label(None) {
                e.cancel();
                self.bump();
            } else {
                return Err(e);
            }
        }
        let attrs = self.parse_inner_attributes()?;

        let mut arms = ThinVec::new();
        while self.token != token::CloseBrace {
            match self.parse_arm() {
                Ok(arm) => arms.push(arm),
                Err(e) => {
                    // Recover by skipping to the end of the block.
                    let guar = e.emit();
                    self.recover_stmt();
                    let span = lo.to(self.token.span);
                    if self.token == token::CloseBrace {
                        self.bump();
                    }
                    // Always push at least one arm to make the match non-empty
                    arms.push(Arm {
                        attrs: Default::default(),
                        pat: Box::new(self.mk_pat(span, ast::PatKind::Err(guar))),
                        guard: None,
                        body: Some(self.mk_expr_err(span, guar)),
                        span,
                        id: DUMMY_NODE_ID,
                        is_placeholder: false,
                    });
                    return Ok(self.mk_expr_with_attrs(
                        span,
                        ExprKind::Match(scrutinee, arms, match_kind),
                        attrs,
                    ));
                }
            }
        }
        let hi = self.token.span;
        self.bump();
        Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs))
    }

    /// Attempt to recover from match arm body with statements and no surrounding braces.
    fn parse_arm_body_missing_braces(
        &mut self,
        first_expr: &Box<Expr>,
        arrow_span: Span,
    ) -> Option<(Span, ErrorGuaranteed)> {
        if self.token != token::Semi {
            return None;
        }
        let start_snapshot = self.create_snapshot_for_diagnostic();
        let semi_sp = self.token.span;
        self.bump(); // `;`
        let mut stmts =
            vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
        let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
            let span = stmts[0].span.to(stmts[stmts.len() - 1].span);

            let guar = this.dcx().emit_err(errors::MatchArmBodyWithoutBraces {
                statements: span,
                arrow: arrow_span,
                num_statements: stmts.len(),
                sub: if stmts.len() > 1 {
                    errors::MatchArmBodyWithoutBracesSugg::AddBraces {
                        left: span.shrink_to_lo(),
                        right: span.shrink_to_hi(),
                        num_statements: stmts.len(),
                    }
                } else {
                    errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
                },
            });
            (span, guar)
        };
        // We might have either a `,` -> `;` typo, or a block without braces. We need
        // a more subtle parsing strategy.
        loop {
            if self.token == token::CloseBrace {
                // We have reached the closing brace of the `match` expression.
                return Some(err(self, stmts));
            }
            if self.token == token::Comma {
                self.restore_snapshot(start_snapshot);
                return None;
            }
            let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
            match self.parse_pat_no_top_alt(None, None) {
                Ok(_pat) => {
                    if self.token == token::FatArrow {
                        // Reached arm end.
                        self.restore_snapshot(pre_pat_snapshot);
                        return Some(err(self, stmts));
                    }
                }
                Err(err) => {
                    err.cancel();
                }
            }

            self.restore_snapshot(pre_pat_snapshot);
            match self.parse_stmt_without_recovery(true, ForceCollect::No, false) {
                // Consume statements for as long as possible.
                Ok(Some(stmt)) => {
                    stmts.push(stmt);
                }
                Ok(None) => {
                    self.restore_snapshot(start_snapshot);
                    break;
                }
                // We couldn't parse either yet another statement missing it's
                // enclosing block nor the next arm's pattern or closing brace.
                Err(stmt_err) => {
                    stmt_err.cancel();
                    self.restore_snapshot(start_snapshot);
                    break;
                }
            }
        }
        None
    }

    pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
        let attrs = self.parse_outer_attributes()?;
        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let lo = this.token.span;
            let (pat, guard) = this.parse_match_arm_pat_and_guard()?;
            let pat = Box::new(pat);

            let span_before_body = this.prev_token.span;
            let arm_body;
            let is_fat_arrow = this.check(exp!(FatArrow));
            let is_almost_fat_arrow =
                TokenKind::FatArrow.similar_tokens().contains(&this.token.kind);

            // this avoids the compiler saying that a `,` or `}` was expected even though
            // the pattern isn't a never pattern (and thus an arm body is required)
            let armless = (!is_fat_arrow && !is_almost_fat_arrow && pat.could_be_never_pattern())
                || matches!(this.token.kind, token::Comma | token::CloseBrace);

            let mut result = if armless {
                // A pattern without a body, allowed for never patterns.
                arm_body = None;
                let span = lo.to(this.prev_token.span);
                this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map(|x| {
                    // Don't gate twice
                    if !pat.contains_never_pattern() {
                        this.psess.gated_spans.gate(sym::never_patterns, span);
                    }
                    x
                })
            } else {
                if let Err(mut err) = this.expect(exp!(FatArrow)) {
                    // We might have a `=>` -> `=` or `->` typo (issue #89396).
                    if is_almost_fat_arrow {
                        err.span_suggestion(
                            this.token.span,
                            "use a fat arrow to start a match arm",
                            "=>",
                            Applicability::MachineApplicable,
                        );
                        if matches!(
                            (&this.prev_token.kind, &this.token.kind),
                            (token::DotDotEq, token::Gt)
                        ) {
                            // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
                            // so we suppress the error here
                            err.delay_as_bug();
                        } else {
                            err.emit();
                        }
                        this.bump();
                    } else {
                        return Err(err);
                    }
                }
                let arrow_span = this.prev_token.span;
                let arm_start_span = this.token.span;

                let attrs = this.parse_outer_attributes()?;
                let (expr, _) =
                    this.parse_expr_res(Restrictions::STMT_EXPR, attrs).map_err(|mut err| {
                        err.span_label(arrow_span, "while parsing the `match` arm starting here");
                        err
                    })?;

                let require_comma =
                    !classify::expr_is_complete(&expr) && this.token != token::CloseBrace;

                if !require_comma {
                    arm_body = Some(expr);
                    // Eat a comma if it exists, though.
                    let _ = this.eat(exp!(Comma));
                    Ok(Recovered::No)
                } else if let Some((span, guar)) =
                    this.parse_arm_body_missing_braces(&expr, arrow_span)
                {
                    let body = this.mk_expr_err(span, guar);
                    arm_body = Some(body);
                    Ok(Recovered::Yes(guar))
                } else {
                    let expr_span = expr.span;
                    arm_body = Some(expr);
                    this.expect_one_of(&[exp!(Comma)], &[exp!(CloseBrace)]).map_err(|mut err| {
                        if this.token == token::FatArrow {
                            let sm = this.psess.source_map();
                            if let Ok(expr_lines) = sm.span_to_lines(expr_span)
                                && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
                                && expr_lines.lines.len() == 2
                            {
                                if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col {
                                    // We check whether there's any trailing code in the parse span,
                                    // if there isn't, we very likely have the following:
                                    //
                                    // X |     &Y => "y"
                                    //   |        --    - missing comma
                                    //   |        |
                                    //   |        arrow_span
                                    // X |     &X => "x"
                                    //   |      - ^^ self.token.span
                                    //   |      |
                                    //   |      parsed until here as `"y" & X`
                                    err.span_suggestion_short(
                                        arm_start_span.shrink_to_hi(),
                                        "missing a comma here to end this `match` arm",
                                        ",",
                                        Applicability::MachineApplicable,
                                    );
                                } else if arm_start_lines.lines[0].end_col + rustc_span::CharPos(1)
                                    == expr_lines.lines[0].end_col
                                {
                                    // similar to the above, but we may typo a `.` or `/` at the end of the line
                                    let comma_span = arm_start_span
                                        .shrink_to_hi()
                                        .with_hi(arm_start_span.hi() + rustc_span::BytePos(1));
                                    if let Ok(res) = sm.span_to_snippet(comma_span)
                                        && (res == "." || res == "/")
                                    {
                                        err.span_suggestion_short(
                                            comma_span,
                                            "you might have meant to write a `,` to end this `match` arm",
                                            ",",
                                            Applicability::MachineApplicable,
                                        );
                                    }
                                }
                            }
                        } else {
                            err.span_label(
                                arrow_span,
                                "while parsing the `match` arm starting here",
                            );
                        }
                        err
                    })
                }
            };

            let hi_span = arm_body.as_ref().map_or(span_before_body, |body| body.span);
            let arm_span = lo.to(hi_span);

            // We want to recover:
            // X |     Some(_) => foo()
            //   |                     - missing comma
            // X |     None => "x"
            //   |     ^^^^ self.token.span
            // as well as:
            // X |     Some(!)
            //   |            - missing comma
            // X |     None => "x"
            //   |     ^^^^ self.token.span
            // But we musn't recover
            // X |     pat[0] => {}
            //   |        ^ self.token.span
            let recover_missing_comma = arm_body.is_some() || pat.could_be_never_pattern();
            if recover_missing_comma {
                result = result.or_else(|err| {
                    // FIXME(compiler-errors): We could also recover `; PAT =>` here

                    // Try to parse a following `PAT =>`, if successful
                    // then we should recover.
                    let mut snapshot = this.create_snapshot_for_diagnostic();
                    let pattern_follows = snapshot
                        .parse_pat_no_top_guard(
                            None,
                            RecoverComma::Yes,
                            RecoverColon::Yes,
                            CommaRecoveryMode::EitherTupleOrPipe,
                        )
                        .map_err(|err| err.cancel())
                        .is_ok();
                    if pattern_follows && snapshot.check(exp!(FatArrow)) {
                        err.cancel();
                        let guar = this.dcx().emit_err(errors::MissingCommaAfterMatchArm {
                            span: arm_span.shrink_to_hi(),
                        });
                        return Ok(Recovered::Yes(guar));
                    }
                    Err(err)
                });
            }
            result?;

            Ok((
                ast::Arm {
                    attrs,
                    pat,
                    guard,
                    body: arm_body,
                    span: arm_span,
                    id: DUMMY_NODE_ID,
                    is_placeholder: false,
                },
                Trailing::No,
                UsePreAttrPos::No,
            ))
        })
    }

    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> {
        if !self.eat_keyword(exp!(If)) {
            // No match arm guard present.
            return Ok(None);
        }

        let mut cond = self.parse_match_guard_condition()?;

        CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);

        Ok(Some(cond))
    }

    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
        if self.token == token::OpenParen {
            let left = self.token.span;
            let pat = self.parse_pat_no_top_guard(
                None,
                RecoverComma::Yes,
                RecoverColon::Yes,
                CommaRecoveryMode::EitherTupleOrPipe,
            )?;
            if let ast::PatKind::Paren(subpat) = &pat.kind
                && let ast::PatKind::Guard(..) = &subpat.kind
            {
                // Detect and recover from `($pat if $cond) => $arm`.
                // FIXME(guard_patterns): convert this to a normal guard instead
                let span = pat.span;
                let ast::PatKind::Paren(subpat) = pat.kind else { unreachable!() };
                let ast::PatKind::Guard(_, mut cond) = subpat.kind else { unreachable!() };
                self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
                let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
                checker.visit_expr(&mut cond);

                let right = self.prev_token.span;
                self.dcx().emit_err(errors::ParenthesesInMatchPat {
                    span: vec![left, right],
                    sugg: errors::ParenthesesInMatchPatSugg { left, right },
                });

                Ok((
                    self.mk_pat(span, ast::PatKind::Wild),
                    (if let Some(guar) = checker.found_incorrect_let_chain {
                        Some(self.mk_expr_err(cond.span, guar))
                    } else {
                        Some(cond)
                    }),
                ))
            } else {
                Ok((pat, self.parse_match_arm_guard()?))
            }
        } else {
            // Regular parser flow:
            let pat = self.parse_pat_no_top_guard(
                None,
                RecoverComma::Yes,
                RecoverColon::Yes,
                CommaRecoveryMode::EitherTupleOrPipe,
            )?;
            Ok((pat, self.parse_match_arm_guard()?))
        }
    }

    fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
            Ok((expr, _)) => Ok(expr),
            Err(mut err) => {
                if self.prev_token == token::OpenBrace {
                    let sugg_sp = self.prev_token.span.shrink_to_lo();
                    // Consume everything within the braces, let's avoid further parse
                    // errors.
                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                    let msg = "you might have meant to start a match arm after the match guard";
                    if self.eat(exp!(CloseBrace)) {
                        let applicability = if self.token != token::FatArrow {
                            // We have high confidence that we indeed didn't have a struct
                            // literal in the match guard, but rather we had some operation
                            // that ended in a path, immediately followed by a block that was
                            // meant to be the match arm.
                            Applicability::MachineApplicable
                        } else {
                            Applicability::MaybeIncorrect
                        };
                        err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
                    }
                }
                Err(err)
            }
        }
    }

    pub(crate) fn is_builtin(&self) -> bool {
        self.token.is_keyword(kw::Builtin) && self.look_ahead(1, |t| *t == token::Pound)
    }

    /// Parses a `try {...}` or `try bikeshed Ty {...}` expression (`try` token already eaten).
    fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box<Expr>> {
        let annotation =
            if self.eat_keyword(exp!(Bikeshed)) { Some(self.parse_ty()?) } else { None };

        let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
        if self.eat_keyword(exp!(Catch)) {
            Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
        } else {
            let span = span_lo.to(body.span);
            let gate_sym =
                if annotation.is_none() { sym::try_blocks } else { sym::try_blocks_heterogeneous };
            self.psess.gated_spans.gate(gate_sym, span);
            Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body, annotation), attrs))
        }
    }

    fn is_do_catch_block(&self) -> bool {
        self.token.is_keyword(kw::Do)
            && self.is_keyword_ahead(1, &[kw::Catch])
            && self.look_ahead(2, |t| *t == token::OpenBrace || t.is_metavar_block())
            && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
    }

    fn is_do_yeet(&self) -> bool {
        self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Yeet])
    }

    fn is_try_block(&self) -> bool {
        self.token.is_keyword(kw::Try)
            && self.look_ahead(1, |t| {
                *t == token::OpenBrace
                    || t.is_metavar_block()
                    || t.kind == TokenKind::Ident(sym::bikeshed, IdentIsRaw::No)
            })
            && self.token_uninterpolated_span().at_least_rust_2018()
    }

    /// Parses an `async move? {...}` or `gen move? {...}` expression.
    fn parse_gen_block(&mut self) -> PResult<'a, Box<Expr>> {
        let lo = self.token.span;
        let kind = if self.eat_keyword(exp!(Async)) {
            if self.eat_keyword(exp!(Gen)) { GenBlockKind::AsyncGen } else { GenBlockKind::Async }
        } else {
            assert!(self.eat_keyword(exp!(Gen)));
            GenBlockKind::Gen
        };
        match kind {
            GenBlockKind::Async => {
                // `async` blocks are stable
            }
            GenBlockKind::Gen | GenBlockKind::AsyncGen => {
                self.psess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span));
            }
        }
        let capture_clause = self.parse_capture_clause()?;
        let decl_span = lo.to(self.prev_token.span);
        let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
        let kind = ExprKind::Gen(capture_clause, body, kind, decl_span);
        Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
    }

    fn is_gen_block(&self, kw: Symbol, lookahead: usize) -> bool {
        self.is_keyword_ahead(lookahead, &[kw])
            && ((
                // `async move {`
                self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use])
                    && self.look_ahead(lookahead + 2, |t| {
                        *t == token::OpenBrace || t.is_metavar_block()
                    })
            ) || (
                // `async {`
                self.look_ahead(lookahead + 1, |t| *t == token::OpenBrace || t.is_metavar_block())
            ))
    }

    pub(super) fn is_async_gen_block(&self) -> bool {
        self.token.is_keyword(kw::Async) && self.is_gen_block(kw::Gen, 1)
    }

    fn is_likely_struct_lit(&self) -> bool {
        // `{ ident, ` and `{ ident: ` cannot start a block.
        self.look_ahead(1, |t| t.is_ident())
            && self.look_ahead(2, |t| t == &token::Comma || t == &token::Colon)
    }

    fn maybe_parse_struct_expr(
        &mut self,
        qself: &Option<Box<ast::QSelf>>,
        path: &ast::Path,
    ) -> Option<PResult<'a, Box<Expr>>> {
        let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
        match (struct_allowed, self.is_likely_struct_lit()) {
            // A struct literal isn't expected and one is pretty much assured not to be present. The
            // only situation that isn't detected is when a struct with a single field was attempted
            // in a place where a struct literal wasn't expected, but regular parser errors apply.
            // Happy path.
            (false, false) => None,
            (true, _) => {
                // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for
                // any kind of recovery. Happy path.
                if let Err(err) = self.expect(exp!(OpenBrace)) {
                    return Some(Err(err));
                }
                Some(self.parse_expr_struct(qself.clone(), path.clone(), true))
            }
            (false, true) => {
                // We have something like `match foo { bar,` or `match foo { bar:`, which means the
                // user might have meant to write a struct literal as part of the `match`
                // discriminant. This is done purely for error recovery.
                let snapshot = self.create_snapshot_for_diagnostic();
                if let Err(err) = self.expect(exp!(OpenBrace)) {
                    return Some(Err(err));
                }
                match self.parse_expr_struct(qself.clone(), path.clone(), false) {
                    Ok(expr) => {
                        // This is a struct literal, but we don't accept them here.
                        self.dcx().emit_err(errors::StructLiteralNotAllowedHere {
                            span: expr.span,
                            sub: errors::StructLiteralNotAllowedHereSugg {
                                left: path.span.shrink_to_lo(),
                                right: expr.span.shrink_to_hi(),
                            },
                        });
                        Some(Ok(expr))
                    }
                    Err(err) => {
                        // We couldn't parse a valid struct, rollback and let the parser emit an
                        // error elsewhere.
                        err.cancel();
                        self.restore_snapshot(snapshot);
                        None
                    }
                }
            }
        }
    }

    fn maybe_recover_bad_struct_literal_path(
        &mut self,
        is_underscore_entry_point: bool,
    ) -> PResult<'a, Option<Box<Expr>>> {
        if self.may_recover()
            && self.check_noexpect(&token::OpenBrace)
            && (!self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
                && self.is_likely_struct_lit())
        {
            let span = if is_underscore_entry_point {
                self.prev_token.span
            } else {
                self.token.span.shrink_to_lo()
            };

            self.bump(); // {
            let expr = self.parse_expr_struct(
                None,
                Path::from_ident(Ident::new(kw::Underscore, span)),
                false,
            )?;

            let guar = if is_underscore_entry_point {
                self.dcx().create_err(errors::StructLiteralPlaceholderPath { span }).emit()
            } else {
                self.dcx()
                    .create_err(errors::StructLiteralWithoutPathLate {
                        span: expr.span,
                        suggestion_span: expr.span.shrink_to_lo(),
                    })
                    .emit()
            };

            Ok(Some(self.mk_expr_err(expr.span, guar)))
        } else {
            Ok(None)
        }
    }

    pub(super) fn parse_struct_fields(
        &mut self,
        pth: ast::Path,
        recover: bool,
        close: ExpTokenPair,
    ) -> PResult<
        'a,
        (
            ThinVec<ExprField>,
            ast::StructRest,
            Option<ErrorGuaranteed>, /* async blocks are forbidden in Rust 2015 */
        ),
    > {
        let mut fields = ThinVec::new();
        let mut base = ast::StructRest::None;
        let mut recovered_async = None;
        let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);

        let async_block_err = |e: &mut Diag<'_>, span: Span| {
            errors::AsyncBlockIn2015 { span }.add_to_diag(e);
            errors::HelpUseLatestEdition::new().add_to_diag(e);
        };

        while self.token != close.tok {
            if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(&close.tok) {
                let exp_span = self.prev_token.span;
                // We permit `.. }` on the left-hand side of a destructuring assignment.
                if self.check(close) {
                    base = ast::StructRest::Rest(self.prev_token.span);
                    break;
                }
                match self.parse_expr() {
                    Ok(e) => base = ast::StructRest::Base(e),
                    Err(e) if recover => {
                        e.emit();
                        self.recover_stmt();
                    }
                    Err(e) => return Err(e),
                }
                self.recover_struct_comma_after_dotdot(exp_span);
                break;
            }

            // Peek the field's ident before parsing its expr in order to emit better diagnostics.
            let peek = self
                .token
                .ident()
                .filter(|(ident, is_raw)| {
                    (!ident.is_reserved() || matches!(is_raw, IdentIsRaw::Yes))
                        && self.look_ahead(1, |tok| *tok == token::Colon)
                })
                .map(|(ident, _)| ident);

            // We still want a field even if its expr didn't parse.
            let field_ident = |this: &Self, guar: ErrorGuaranteed| {
                peek.map(|ident| {
                    let span = ident.span;
                    ExprField {
                        ident,
                        span,
                        expr: this.mk_expr_err(span, guar),
                        is_shorthand: false,
                        attrs: AttrVec::new(),
                        id: DUMMY_NODE_ID,
                        is_placeholder: false,
                    }
                })
            };

            let parsed_field = match self.parse_expr_field() {
                Ok(f) => Ok(f),
                Err(mut e) => {
                    if pth == kw::Async {
                        async_block_err(&mut e, pth.span);
                    } else {
                        e.span_label(pth.span, "while parsing this struct");
                    }

                    if let Some((ident, _)) = self.token.ident()
                        && !self.token.is_reserved_ident()
                        && self.look_ahead(1, |t| {
                            AssocOp::from_token(t).is_some()
                                || matches!(
                                    t.kind,
                                    token::OpenParen | token::OpenBracket | token::OpenBrace
                                )
                                || *t == token::Dot
                        })
                    {
                        // Looks like they tried to write a shorthand, complex expression,
                        // E.g.: `n + m`, `f(a)`, `a[i]`, `S { x: 3 }`, or `x.y`.
                        e.span_suggestion_verbose(
                            self.token.span.shrink_to_lo(),
                            "try naming a field",
                            &format!("{ident}: ",),
                            Applicability::MaybeIncorrect,
                        );
                    }
                    if in_if_guard && close.token_type == TokenType::CloseBrace {
                        return Err(e);
                    }

                    if !recover {
                        return Err(e);
                    }

                    let guar = e.emit();
                    if pth == kw::Async {
                        recovered_async = Some(guar);
                    }

                    // If we encountered an error which we are recovering from, treat the struct
                    // as if it has a `..` in it, because we don’t know what fields the user
                    // might have *intended* it to have.
                    //
                    // This assignment will be overwritten if we actually parse a `..` later.
                    //
                    // (Note that this code is duplicated between here and below in comma parsing.
                    base = ast::StructRest::NoneWithError(guar);

                    // If the next token is a comma, then try to parse
                    // what comes next as additional fields, rather than
                    // bailing out until next `}`.
                    if self.token != token::Comma {
                        self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
                        if self.token != token::Comma {
                            break;
                        }
                    }

                    Err(guar)
                }
            };

            let is_shorthand = parsed_field.as_ref().is_ok_and(|f| f.is_shorthand);
            // A shorthand field can be turned into a full field with `:`.
            // We should point this out.
            self.check_or_expected(!is_shorthand, TokenType::Colon);

            match self.expect_one_of(&[exp!(Comma)], &[close]) {
                Ok(_) => {
                    if let Ok(f) = parsed_field.or_else(|guar| field_ident(self, guar).ok_or(guar))
                    {
                        // Only include the field if there's no parse error for the field name.
                        fields.push(f);
                    }
                }
                Err(mut e) => {
                    if pth == kw::Async {
                        async_block_err(&mut e, pth.span);
                    } else {
                        e.span_label(pth.span, "while parsing this struct");
                        if peek.is_some() {
                            e.span_suggestion(
                                self.prev_token.span.shrink_to_hi(),
                                "try adding a comma",
                                ",",
                                Applicability::MachineApplicable,
                            );
                        }
                    }
                    if !recover {
                        return Err(e);
                    }
                    let guar = e.emit();
                    if pth == kw::Async {
                        recovered_async = Some(guar);
                    } else if let Some(f) = field_ident(self, guar) {
                        fields.push(f);
                    }

                    // See comment above on this same assignment inside of field parsing.
                    base = ast::StructRest::NoneWithError(guar);

                    self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
                    let _ = self.eat(exp!(Comma));
                }
            }
        }
        Ok((fields, base, recovered_async))
    }

    /// Precondition: already parsed the '{'.
    pub(super) fn parse_expr_struct(
        &mut self,
        qself: Option<Box<ast::QSelf>>,
        pth: ast::Path,
        recover: bool,
    ) -> PResult<'a, Box<Expr>> {
        let lo = pth.span;
        let (fields, base, recovered_async) =
            self.parse_struct_fields(pth.clone(), recover, exp!(CloseBrace))?;
        let span = lo.to(self.token.span);
        self.expect(exp!(CloseBrace))?;
        let expr = if let Some(guar) = recovered_async {
            ExprKind::Err(guar)
        } else {
            ExprKind::Struct(Box::new(ast::StructExpr { qself, path: pth, fields, rest: base }))
        };
        Ok(self.mk_expr(span, expr))
    }

    fn recover_struct_comma_after_dotdot(&mut self, span: Span) {
        if self.token != token::Comma {
            return;
        }
        self.dcx().emit_err(errors::CommaAfterBaseStruct {
            span: span.to(self.prev_token.span),
            comma: self.token.span,
        });
        self.recover_stmt();
    }

    fn recover_struct_field_dots(&mut self, close: &TokenKind) -> bool {
        if !self.look_ahead(1, |t| t == close) && self.eat(exp!(DotDotDot)) {
            // recover from typo of `...`, suggest `..`
            let span = self.prev_token.span;
            self.dcx().emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
            return true;
        }
        false
    }

    /// Converts an ident into 'label and emits an "expected a label, found an identifier" error.
    fn recover_ident_into_label(&mut self, ident: Ident) -> Label {
        // Convert `label` -> `'label`,
        // so that nameres doesn't complain about non-existing label
        let label = format!("'{}", ident.name);
        let ident = Ident::new(Symbol::intern(&label), ident.span);

        self.dcx().emit_err(errors::ExpectedLabelFoundIdent {
            span: ident.span,
            start: ident.span.shrink_to_lo(),
        });

        Label { ident }
    }

    /// Parses `ident (COLON expr)?`.
    fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
        let attrs = self.parse_outer_attributes()?;
        self.recover_vcs_conflict_marker();
        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let lo = this.token.span;

            // Check if a colon exists one ahead. This means we're parsing a fieldname.
            let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq);
            // Proactively check whether parsing the field will be incorrect.
            let is_wrong = this.token.is_non_reserved_ident()
                && !this.look_ahead(1, |t| {
                    t == &token::Colon
                        || t == &token::Eq
                        || t == &token::Comma
                        || t == &token::CloseBrace
                        || t == &token::CloseParen
                });
            if is_wrong {
                return Err(this.dcx().create_err(errors::ExpectedStructField {
                    span: this.look_ahead(1, |t| t.span),
                    ident_span: this.token.span,
                    token: this.look_ahead(1, |t| *t),
                }));
            }
            let (ident, expr) = if is_shorthand {
                // Mimic `x: x` for the `x` field shorthand.
                let ident = this.parse_ident_common(false)?;
                let path = ast::Path::from_ident(ident);
                (ident, this.mk_expr(ident.span, ExprKind::Path(None, path)))
            } else {
                let ident = this.parse_field_name()?;
                this.error_on_eq_field_init(ident);
                this.bump(); // `:`
                (ident, this.parse_expr()?)
            };

            Ok((
                ast::ExprField {
                    ident,
                    span: lo.to(expr.span),
                    expr,
                    is_shorthand,
                    attrs,
                    id: DUMMY_NODE_ID,
                    is_placeholder: false,
                },
                Trailing::from(this.token == token::Comma),
                UsePreAttrPos::No,
            ))
        })
    }

    /// Check for `=`. This means the source incorrectly attempts to
    /// initialize a field with an eq rather than a colon.
    fn error_on_eq_field_init(&self, field_name: Ident) {
        if self.token != token::Eq {
            return;
        }

        self.dcx().emit_err(errors::EqFieldInit {
            span: self.token.span,
            eq: field_name.span.shrink_to_hi().to(self.token.span),
        });
    }

    fn err_dotdotdot_syntax(&self, span: Span) {
        self.dcx().emit_err(errors::DotDotDot { span });
    }

    fn err_larrow_operator(&self, span: Span) {
        self.dcx().emit_err(errors::LeftArrowOperator { span });
    }

    fn mk_assign_op(&self, assign_op: AssignOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
        ExprKind::AssignOp(assign_op, lhs, rhs)
    }

    fn mk_range(
        &mut self,
        start: Option<Box<Expr>>,
        end: Option<Box<Expr>>,
        limits: RangeLimits,
    ) -> ExprKind {
        if end.is_none() && limits == RangeLimits::Closed {
            let guar = self.inclusive_range_with_incorrect_end();
            ExprKind::Err(guar)
        } else {
            ExprKind::Range(start, end, limits)
        }
    }

    fn mk_unary(&self, unop: UnOp, expr: Box<Expr>) -> ExprKind {
        ExprKind::Unary(unop, expr)
    }

    fn mk_binary(&self, binop: BinOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
        ExprKind::Binary(binop, lhs, rhs)
    }

    fn mk_index(&self, expr: Box<Expr>, idx: Box<Expr>, brackets_span: Span) -> ExprKind {
        ExprKind::Index(expr, idx, brackets_span)
    }

    fn mk_call(&self, f: Box<Expr>, args: ThinVec<Box<Expr>>) -> ExprKind {
        ExprKind::Call(f, args)
    }

    fn mk_await_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
        let span = lo.to(self.prev_token.span);
        let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span));
        self.recover_from_await_method_call();
        await_expr
    }

    fn mk_use_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
        let span = lo.to(self.prev_token.span);
        let use_expr = self.mk_expr(span, ExprKind::Use(self_arg, self.prev_token.span));
        self.recover_from_use();
        use_expr
    }

    pub(crate) fn mk_expr_with_attrs(
        &self,
        span: Span,
        kind: ExprKind,
        attrs: AttrVec,
    ) -> Box<Expr> {
        Box::new(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
    }

    pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> Box<Expr> {
        self.mk_expr_with_attrs(span, kind, AttrVec::new())
    }

    pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Expr> {
        self.mk_expr(span, ExprKind::Err(guar))
    }

    pub(crate) fn mk_unit_expr(&self, span: Span) -> Box<Expr> {
        self.mk_expr(span, ExprKind::Tup(Default::default()))
    }

    pub(crate) fn mk_closure_expr(&self, span: Span, body: Box<Expr>) -> Box<Expr> {
        self.mk_expr(
            span,
            ast::ExprKind::Closure(Box::new(ast::Closure {
                binder: rustc_ast::ClosureBinder::NotPresent,
                constness: rustc_ast::Const::No,
                movability: rustc_ast::Movability::Movable,
                capture_clause: rustc_ast::CaptureBy::Ref,
                coroutine_kind: None,
                fn_decl: Box::new(rustc_ast::FnDecl {
                    inputs: Default::default(),
                    output: rustc_ast::FnRetTy::Default(span),
                }),
                fn_arg_span: span,
                fn_decl_span: span,
                body,
            })),
        )
    }

    /// Create expression span ensuring the span of the parent node
    /// is larger than the span of lhs and rhs, including the attributes.
    fn mk_expr_sp(&self, lhs: &Box<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
        lhs.attrs
            .iter()
            .find(|a| a.style == AttrStyle::Outer)
            .map_or(lhs_span, |a| a.span)
            .to(op_span)
            .to(rhs_span)
    }

    fn collect_tokens_for_expr(
        &mut self,
        attrs: AttrWrapper,
        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, Box<Expr>>,
    ) -> PResult<'a, Box<Expr>> {
        self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let res = f(this, attrs)?;
            let trailing = Trailing::from(
                this.restrictions.contains(Restrictions::STMT_EXPR)
                     && this.token == token::Semi
                // FIXME: pass an additional condition through from the place
                // where we know we need a comma, rather than assuming that
                // `#[attr] expr,` always captures a trailing comma.
                || this.token == token::Comma,
            );
            Ok((res, trailing, UsePreAttrPos::No))
        })
    }
}

/// Could this lifetime/label be an unclosed char literal? For example, `'a`
/// could be, but `'abc` could not.
pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool {
    ident.name.as_str().starts_with('\'')
        && unescape_char(ident.without_first_quote().name.as_str()).is_ok()
}

/// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on
/// 2024 and later). In case of edition dependence, specify the currently present edition.
pub enum LetChainsPolicy {
    AlwaysAllowed,
    EditionDependent { current_edition: Edition },
}

/// Visitor to check for invalid use of `ExprKind::Let` that can't
/// easily be caught in parsing. For example:
///
/// ```rust,ignore (example)
/// // Only know that the let isn't allowed once the `||` token is reached
/// if let Some(x) = y || true {}
/// // Only know that the let isn't allowed once the second `=` token is reached.
/// if let Some(x) = y && z = 1 {}
/// ```
struct CondChecker<'a> {
    parser: &'a Parser<'a>,
    let_chains_policy: LetChainsPolicy,
    depth: u32,
    forbid_let_reason: Option<errors::ForbiddenLetReason>,
    missing_let: Option<errors::MaybeMissingLet>,
    comparison: Option<errors::MaybeComparison>,
    found_incorrect_let_chain: Option<ErrorGuaranteed>,
}

impl<'a> CondChecker<'a> {
    fn new(parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy) -> Self {
        CondChecker {
            parser,
            forbid_let_reason: None,
            missing_let: None,
            comparison: None,
            let_chains_policy,
            found_incorrect_let_chain: None,
            depth: 0,
        }
    }
}

impl MutVisitor for CondChecker<'_> {
    fn visit_expr(&mut self, e: &mut Expr) {
        self.depth += 1;

        let span = e.span;
        match e.kind {
            ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => {
                if let Some(reason) = self.forbid_let_reason {
                    let error = match reason {
                        errors::ForbiddenLetReason::NotSupportedOr(or_span) => {
                            self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span })
                        }
                        _ => {
                            let guar =
                                self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet {
                                    span,
                                    reason,
                                    missing_let: self.missing_let,
                                    comparison: self.comparison,
                                });
                            if let Some(_) = self.missing_let {
                                self.found_incorrect_let_chain = Some(guar);
                            }
                            guar
                        }
                    };
                    *recovered = Recovered::Yes(error);
                } else if self.depth > 1 {
                    // Top level `let` is always allowed; only gate chains
                    match self.let_chains_policy {
                        LetChainsPolicy::AlwaysAllowed => (),
                        LetChainsPolicy::EditionDependent { current_edition } => {
                            if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() {
                                self.parser.dcx().emit_err(errors::LetChainPre2024 { span });
                            }
                        }
                    }
                }
            }
            ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
                mut_visit::walk_expr(self, e);
            }
            ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _)
                if let None | Some(errors::ForbiddenLetReason::NotSupportedOr(_)) =
                    self.forbid_let_reason =>
            {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason = Some(errors::ForbiddenLetReason::NotSupportedOr(or_span));
                mut_visit::walk_expr(self, e);
                self.forbid_let_reason = forbid_let_reason;
            }
            ExprKind::Paren(ref inner)
                if let None | Some(errors::ForbiddenLetReason::NotSupportedParentheses(_)) =
                    self.forbid_let_reason =>
            {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason =
                    Some(errors::ForbiddenLetReason::NotSupportedParentheses(inner.span));
                mut_visit::walk_expr(self, e);
                self.forbid_let_reason = forbid_let_reason;
            }
            ExprKind::Assign(ref lhs, ref rhs, span) => {
                if let ExprKind::Call(_, _) = &lhs.kind {
                    fn get_path_from_rhs(e: &Expr) -> Option<(u32, &Path)> {
                        fn inner(e: &Expr, depth: u32) -> Option<(u32, &Path)> {
                            match &e.kind {
                                ExprKind::Binary(_, lhs, _) => inner(lhs, depth + 1),
                                ExprKind::Path(_, path) => Some((depth, path)),
                                _ => None,
                            }
                        }

                        inner(e, 0)
                    }

                    if let Some((depth, path)) = get_path_from_rhs(rhs) {
                        // For cases like if Some(_) = x && let Some(_) = y && let Some(_) = z
                        // This return let Some(_) = y expression
                        fn find_let_some(expr: &Expr) -> Option<&Expr> {
                            match &expr.kind {
                                ExprKind::Let(..) => Some(expr),

                                ExprKind::Binary(op, lhs, rhs) if op.node == BinOpKind::And => {
                                    find_let_some(lhs).or_else(|| find_let_some(rhs))
                                }

                                _ => None,
                            }
                        }

                        let expr_span = lhs.span.to(path.span);

                        if let Some(later_rhs) = find_let_some(rhs)
                            && depth > 0
                        {
                            let guar = self.parser.dcx().emit_err(errors::LetChainMissingLet {
                                span: lhs.span,
                                label_span: expr_span,
                                rhs_span: later_rhs.span,
                                sug_span: lhs.span.shrink_to_lo(),
                            });

                            self.found_incorrect_let_chain = Some(guar);
                        }
                    }
                }

                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden);
                let missing_let = self.missing_let;
                if let ExprKind::Binary(_, _, rhs) = &lhs.kind
                    && let ExprKind::Path(_, _)
                    | ExprKind::Struct(_)
                    | ExprKind::Call(_, _)
                    | ExprKind::Array(_) = rhs.kind
                {
                    self.missing_let =
                        Some(errors::MaybeMissingLet { span: rhs.span.shrink_to_lo() });
                }
                let comparison = self.comparison;
                self.comparison = Some(errors::MaybeComparison { span: span.shrink_to_hi() });
                mut_visit::walk_expr(self, e);
                self.forbid_let_reason = forbid_let_reason;
                self.missing_let = missing_let;
                self.comparison = comparison;
            }
            ExprKind::Unary(_, _)
            | ExprKind::Await(_, _)
            | ExprKind::Use(_, _)
            | ExprKind::AssignOp(_, _, _)
            | ExprKind::Range(_, _, _)
            | ExprKind::Try(_)
            | ExprKind::AddrOf(_, _, _)
            | ExprKind::Binary(_, _, _)
            | ExprKind::Field(_, _)
            | ExprKind::Index(_, _, _)
            | ExprKind::Call(_, _)
            | ExprKind::MethodCall(_)
            | ExprKind::Tup(_)
            | ExprKind::Paren(_) => {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden);
                mut_visit::walk_expr(self, e);
                self.forbid_let_reason = forbid_let_reason;
            }
            ExprKind::Cast(ref mut op, _)
            | ExprKind::Type(ref mut op, _)
            | ExprKind::UnsafeBinderCast(_, ref mut op, _) => {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden);
                self.visit_expr(op);
                self.forbid_let_reason = forbid_let_reason;
            }
            ExprKind::Let(_, _, _, Recovered::Yes(_))
            | ExprKind::Array(_)
            | ExprKind::ConstBlock(_)
            | ExprKind::Lit(_)
            | ExprKind::If(_, _, _)
            | ExprKind::While(_, _, _)
            | ExprKind::ForLoop { .. }
            | ExprKind::Loop(_, _, _)
            | ExprKind::Match(_, _, _)
            | ExprKind::Closure(_)
            | ExprKind::Block(_, _)
            | ExprKind::Gen(_, _, _, _)
            | ExprKind::TryBlock(_, _)
            | ExprKind::Underscore
            | ExprKind::Path(_, _)
            | ExprKind::Break(_, _)
            | ExprKind::Continue(_)
            | ExprKind::Ret(_)
            | ExprKind::InlineAsm(_)
            | ExprKind::OffsetOf(_, _)
            | ExprKind::MacCall(_)
            | ExprKind::Struct(_)
            | ExprKind::Repeat(_, _)
            | ExprKind::Yield(_)
            | ExprKind::Yeet(_)
            | ExprKind::Become(_)
            | ExprKind::IncludedBytes(_)
            | ExprKind::FormatArgs(_)
            | ExprKind::Err(_)
            | ExprKind::Dummy => {
                // These would forbid any let expressions they contain already.
            }
        }
        self.depth -= 1;
    }
}
