// 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::BuiltinLintDiag;
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_span::edition::Edition;
use rustc_span::source_map::{self, Spanned};
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Symbol, kw, 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(source_map::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(source_map::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(source_map::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,
                    }
                {
                    self.psess.buffer_lint(
                        BREAK_WITH_LABEL_AND_LOOP,
                        lo.to(expr.span),
                        ast::CRATE_NODE_ID,
                        BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
                    );
                }

                // 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(),
                    }
                } 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;
    }
}
