// ignore-tidy-file-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::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, ForLoop, Guard, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind,
    Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
};
use rustc_ast_pretty::pprust;
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::diagnostics::report_lit_error;
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Spanned, Symbol, kw, respan, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::instrument;

use super::diagnostics::SnapshotParser;
use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
    AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle,
    Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos,
};
use crate::diagnostics::ExprParenthesesNeeded;
use crate::{diagnostics, 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();
        self.parse_expr_res(Restrictions::empty())
    }

    /// 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_after_attrs(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) -> PResult<'a, AnonConst> {
        self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
    }

    fn parse_expr_catch_underscore(
        &mut self,
        restrictions: Restrictions,
    ) -> PResult<'a, Box<Expr>> {
        match self.parse_expr_res(restrictions) {
            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) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        self.parse_expr_res_after_attrs(r, attrs).map(|(expr, _)| expr)
    }

    /// Same as `parse_expr_res`, but with attributes already pre-parsed.
    /// 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`).
    #[inline]
    pub(super) fn parse_expr_res_after_attrs(
        &mut self,
        r: Restrictions,
        attrs: AttrWrapper,
    ) -> PResult<'a, (Box<Expr>, bool)> {
        self.with_res(r, |this| this.parse_expr_assoc_after_attrs(Bound::Unbounded, attrs))
    }

    /// Parses an associative expression with operators of at least `min_prec` precedence.
    pub(super) fn parse_expr_assoc(
        &mut self,
        min_prec: Bound<ExprPrecedence>,
    ) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        self.parse_expr_assoc_after_attrs(min_prec, attrs).map(|(expr, _)| expr)
    }

    /// Same as `parse_expr_assoc`, but with attributes already pre-parsed.
    /// 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_after_attrs(
        &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(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(
        &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(diagnostics::InvalidComparisonOperator {
                    span: sp,
                    invalid: invalid.clone(),
                    sub: diagnostics::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(diagnostics::InvalidComparisonOperator {
                    span: sp,
                    invalid: "<>".into(),
                    sub: diagnostics::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(diagnostics::InvalidComparisonOperator {
                    span: sp,
                    invalid: "<=>".into(),
                    sub: diagnostics::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| {
                this.parse_expr_assoc(min_prec)
            })?;

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

        Ok((lhs, parsed_something))
    }

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

    /// We've found an expression that would be parsed as a statement,
    /// but the next token implies this should be parsed as an expression.
    /// For example: `if let Some(x) = x { x } else { 0 } / 2`.
    fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
        self.dcx().emit_err(diagnostics::FoundExprWouldBeStmt {
            span: self.token.span,
            token: pprust::token_to_string(&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(diagnostics::InvalidLogicalOperator {
                    span: self.token.span,
                    incorrect: "and".into(),
                    sub: diagnostics::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(diagnostics::InvalidLogicalOperator {
                    span: self.token.span,
                    incorrect: "or".into(),
                    sub: diagnostics::InvalidLogicalOperatorSub::Disjunction(self.token.span),
                });
                (AssocOp::Binary(BinOpKind::Or), span)
            }
            _ => return None,
        };
        Some(respan(span, op))
    }

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

    /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
    /// The other two variants are handled in `parse_prefix_range_expr` below.
    fn parse_expr_range(
        &mut self,
        prec: ExprPrecedence,
        lhs: Box<Expr>,
        limits: RangeLimits,
        cur_op_span: Span,
    ) -> PResult<'a, Box<Expr>> {
        let rhs = if self.is_at_start_of_range_notation_rhs() {
            let maybe_lt = self.token;
            Some(
                self.parse_expr_assoc(Bound::Excluded(prec))
                    .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
            )
        } 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 = diagnostics::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);
        self.collect_tokens_for_expr(AttrWrapper::empty(), |this, _empty_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.
                this.parse_expr_assoc(Bound::Excluded(op.unwrap().precedence()))
                    .map(|expr| (lo.to(expr.span), Some(expr)))
                    .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(span, range))
        })
    }

    /// 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 = diagnostics::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(); // `+`
                Ok(this.parse_expr_prefix_common(lo)?.1)
            }
            // 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.token.is_keyword(kw::Move)
                    && this.look_ahead(1, |t| *t == token::OpenParen) =>
            {
                make_it!(this, attrs, |this, _| this.parse_expr_move(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>)> {
        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)> {
        self.bump(); // `op`
        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(diagnostics::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)> {
        self.bump(); // `box`
        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 = diagnostics::AddBoxNew { box_kw_and_lo, hi };
        let guar = self.dcx().emit_err(diagnostics::BoxSyntaxRemoved { span, sugg });
        Ok((span, ExprKind::Err(guar)))
    }

    fn parse_expr_move(&mut self, move_kw: Span) -> PResult<'a, (Span, ExprKind)> {
        self.bump();
        self.psess.gated_spans.gate(sym::move_expr, move_kw);
        self.expect(exp!(OpenParen))?;
        let expr = self.parse_expr()?;
        self.expect(exp!(CloseParen))?;
        let span = move_kw.to(self.prev_token.span);
        Ok((span, ExprKind::Move(expr, move_kw)))
    }

    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() {
            diagnostics::NotAsNegationOperatorSub::SuggestNotBitwise
        } else if negated_token.is_bool_lit() {
            diagnostics::NotAsNegationOperatorSub::SuggestNotLogical
        } else {
            diagnostics::NotAsNegationOperatorSub::SuggestNotDefault
        };

        self.dcx().emit_err(diagnostics::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(diagnostics::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(diagnostics::ComparisonInterpretedAsGeneric {
                                    comparison: self.token.span,
                                    r#type: pprust::path_to_string(&path),
                                    args: args_span,
                                    suggestion: diagnostics::ComparisonInterpretedAsGenericSugg {
                                        left: expr.span.shrink_to_lo(),
                                        right: expr.span.shrink_to_hi(),
                                    },
                                })
                            }
                            token::Shl => {
                                self.dcx().emit_err(diagnostics::ShiftInterpretedAsGeneric {
                                    shift: self.token.span,
                                    r#type: pprust::path_to_string(&path),
                                    args: args_span,
                                    suggestion: diagnostics::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 (span, expr) = self.parse_expr_prefix_common(lo)?;
        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(diagnostics::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_mut_or_const().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(diagnostics::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(diagnostics::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, ThinVec<Ident>> {
        let mut fields = ThinVec::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(diagnostics::ArrayIndexInOffsetOf(span));
                        current = left;
                    }
                    ExprKind::Lit(token::Lit {
                        kind: token::Float | token::Integer,
                        symbol,
                        suffix,
                    }) => {
                        if let Some(suffix) = suffix {
                            self.dcx().emit_err(diagnostics::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(diagnostics::InvalidOffsetOf(current.span));
                                break;
                            }
                        }
                        break;
                    }
                    _ => {
                        self.dcx().emit_err(diagnostics::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(diagnostics::InvalidOffsetOf(self.token.span));
                break;
            }
        }
        if let Some(dot) = trailing_dot {
            self.dcx().emit_err(diagnostics::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(diagnostics::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 call_depth = self.token_cursor.depth();

        let seq = match self.parse_expr_paren_seq() {
            Ok(args) => Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args))),
            Err(err)
                if self.is_expected_raw_ref_mut() && self.token_cursor.depth() == call_depth =>
            {
                let guar = err.emit();
                // Preserve the call expression so later passes can still diagnose the callee,
                // while treating the malformed `&raw <expr>` argument as an error expression.
                let args = self.recover_raw_ref_call_args(guar);
                return self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args));
            }
            Err(err) => Err(err),
        };
        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),
        }
    }

    fn recover_raw_ref_call_args(&mut self, guar: ErrorGuaranteed) -> ThinVec<Box<Expr>> {
        let err_span = self.prev_token.span.to(self.token.span);
        let mut args = thin_vec![self.mk_expr_err(err_span, guar)];
        while !self.token.kind.is_close_delim_or_eof() {
            if self.eat(exp!(Comma)) {
                if !self.token.kind.is_close_delim_or_eof() {
                    args.push(self.mk_expr_err(self.prev_token.span.shrink_to_hi(), guar));
                }
            } else {
                self.parse_token_tree();
            }
        }
        let _ = self.eat(exp!(CloseParen));
        args
    }

    /// 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();
                            let type_str = pprust::path_to_string(&path);
                            self.dcx()
                                .create_err(diagnostics::ParenthesesWithStructFields {
                                    span,
                                    braces_for_struct: diagnostics::BracesForStructLiteral {
                                        first: open_paren,
                                        second: close_paren,
                                        r#type: type_str.clone(),
                                    },
                                    no_fields_for_fn: diagnostics::NoFieldsForFnCall {
                                        r#type: type_str,
                                        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_token = self.prev_token;
        let open_delim_span = self.token.span;
        self.bump(); // `[`
        let index = self.parse_expr()?;
        self.suggest_missing_semicolon_before_array(prev_token.span, open_delim_span)?;
        self.expect(exp!(CloseBracket)).map_err(|mut e| {
            if let TokenKind::Ident(_, _) = prev_token.kind {
                e.span_suggestion_verbose(
                    prev_token.span.shrink_to_hi(),
                    "you might have meant to call a macro",
                    "!".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
            e
        })?;
        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(diagnostics::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()?;
                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_verbose(
                        eq_lt,
                        "you might have meant to write a \"less than or equal to\" comparison",
                        "<=",
                        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(diagnostics::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(diagnostics::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(diagnostics::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 = diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::LabeledLoopInBreak {
                span: lexpr.span,
                sub: diagnostics::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(ForLoop { label: None, .. })
                        | ExprKind::Loop(_, None, _) => true,
                        ExprKind::Block(block, None) => {
                            matches!(block.rules, BlockCheckMode::Default)
                        }
                        _ => false,
                    }
                {
                    let span = expr.span;
                    self.psess.buffer_lint(
                        BREAK_WITH_LABEL_AND_LOOP,
                        lo.to(expr.span),
                        ast::CRATE_NODE_ID,
                        diagnostics::BreakWithLabelAndLoop {
                            sub: diagnostics::BreakWithLabelAndLoopSub {
                                left: span.shrink_to_lo(),
                                right: span.shrink_to_hi(),
                            },
                        },
                    );
                }

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

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

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

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

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

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

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

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

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

        let Some((ident, IdentIsRaw::No)) = self.token.ident() else {
            let err =
                self.dcx().create_err(diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::ArrayBracketsInsteadOfBraces {
                    span: arr.span,
                    sub: diagnostics::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(diagnostics::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(diagnostics::InvalidBlockMacroSegment {
                span: self.token.span,
                context: lo.to(self.token.span),
                wrap: diagnostics::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;
                match self.parse_expr_res(restrictions) {
                    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((Delimiter::Parenthesis, _)) = self.token_cursor.parent_delim_and_span()
            && 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) {
                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(diagnostics::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(diagnostics::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(diagnostics::IfExpressionMissingThenBlock {
                        if_span: lo,
                        missing_then_block_sub:
                            diagnostics::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(diagnostics::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(|| diagnostics::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });

                let guar = self.dcx().emit_err(diagnostics::IfExpressionMissingThenBlock {
                    if_span: lo,
                    missing_then_block_sub:
                        diagnostics::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_verbose(
                                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_verbose(
                                    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 mut cond =
            self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET)?;

        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: Recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
            let err = diagnostics::ExpectedExpressionFoundLet {
                span: self.token.span,
                reason: diagnostics::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(diagnostics::ExpectedEqForLetExpr {
                span: self.token.span,
                sugg_span: self.token.span,
            });
            self.bump();
        } else {
            self.expect(exp!(Eq))?;
        }
        let expr = self.parse_expr_assoc(Bound::Excluded(prec_let_scrutinee_needs_par()))?;
        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(diagnostics::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(diagnostics::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(diagnostics::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 expr = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL) {
                    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(diagnostics::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: diagnostics::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 expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL)?;
        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(diagnostics::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(Box::new(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(Box::new(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(diagnostics::LoopElseNotSupported {
                span: else_span.to(else_clause.span),
                loop_kind,
                loop_kw,
            });
        }
        Ok(())
    }

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

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

    /// Whether the `for` loop header already contains an `in` before its body.
    /// If it does, the binding is malformed (e.g. `for i i in 0..10`) rather
    /// than missing `in`, so suggesting another `in` would just be invalid too.
    fn for_loop_head_has_in(&self) -> bool {
        let mut dist = 0;
        loop {
            let (is_in, is_end) = self.look_ahead(dist, |t| {
                (t.is_keyword(kw::In), matches!(t.kind, token::OpenBrace | token::Eof))
            });
            if is_in {
                return true;
            }
            if is_end {
                return false;
            }
            dist += 1;
        }
    }

    /// 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(diagnostics::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 scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL)?;

        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(diagnostics::MatchArmBodyWithoutBraces {
                statements: span,
                arrow: arrow_span,
                num_statements: stmts.len(),
                sub: if stmts.len() > 1 {
                    diagnostics::MatchArmBodyWithoutBracesSugg::AddBraces {
                        left: span.shrink_to_lo(),
                        right: span.shrink_to_hi(),
                        num_statements: stmts.len(),
                    }
                } else {
                    diagnostics::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(stmt) => {
                    stmts.push(stmt);
                }
                // 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_verbose(
                            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 expr =
                    this.parse_expr_res(Restrictions::STMT_EXPR).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(diagnostics::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,
            ))
        })
    }

    pub(crate) fn eat_metavar_guard(&mut self) -> Option<Box<Guard>> {
        self.eat_metavar_seq(MetaVarKind::Guard, |this| {
            this.expect_match_arm_guard(ForceCollect::Yes)
        })
    }

    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Guard>>> {
        if let Some(guard) = self.eat_metavar_guard() {
            return Ok(Some(guard));
        }

        if !self.eat_keyword(exp!(If)) {
            // No match arm guard present.
            return Ok(None);
        }
        self.expect_match_arm_guard_cond(ForceCollect::No).map(Some)
    }

    pub(crate) fn expect_match_arm_guard(
        &mut self,
        force_collect: ForceCollect,
    ) -> PResult<'a, Box<Guard>> {
        if let Some(guard) = self.eat_metavar_guard() {
            return Ok(guard);
        }

        self.expect_keyword(exp!(If))?;
        self.expect_match_arm_guard_cond(force_collect)
    }

    fn expect_match_arm_guard_cond(
        &mut self,
        force_collect: ForceCollect,
    ) -> PResult<'a, Box<Guard>> {
        let leading_if_span = self.prev_token.span;

        let mut cond = self.parse_match_guard_condition(force_collect)?;
        let cond_span = cond.span;

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

        let guard = Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) };
        Ok(Box::new(guard))
    }

    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Guard>>)> {
        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 guard) = subpat.kind else { unreachable!() };
                self.psess.gated_spans.ungate_last(sym::guard_patterns, guard.span());
                let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
                checker.visit_expr(&mut guard.cond);

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

                if let Some(guar) = checker.found_incorrect_let_chain {
                    guard.cond = *self.mk_expr_err(guard.span(), guar);
                }
                Ok((self.mk_pat(span, ast::PatKind::Wild), Some(guard)))
            } 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,
        force_collect: ForceCollect,
    ) -> PResult<'a, Box<Expr>> {
        let attrs = self.parse_outer_attributes()?;
        let expr = self.collect_tokens(
            None,
            AttrWrapper::empty(),
            force_collect,
            |this, _empty_attrs| {
                match this.parse_expr_res_after_attrs(
                    Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD,
                    attrs,
                ) {
                    Ok((expr, _)) => Ok((expr, Trailing::No, UsePreAttrPos::No)),
                    Err(mut err) => {
                        if this.prev_token == token::OpenBrace {
                            let sugg_sp = this.prev_token.span.shrink_to_lo();
                            // Consume everything within the braces, let's avoid further parse
                            // errors.
                            this.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                            let msg =
                                "you might have meant to start a match arm after the match guard";
                            if this.eat(exp!(CloseBrace)) {
                                let applicability = if this.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)
                    }
                }
            },
        )?;
        Ok(expr)
    }

    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(diagnostics::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(diagnostics::StructLiteralNotAllowedHere {
                            span: expr.span,
                            sub: diagnostics::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(diagnostics::StructLiteralPlaceholderPath { span }).emit()
            } else {
                self.dcx()
                    .create_err(diagnostics::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| {
            diagnostics::AsyncBlockIn2015 { span }.add_to_diag(e);
            diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::ExpectedStructField {
                    span: this.look_ahead(1, |t| t.span),
                    ident_span: this.token.span,
                    token: pprust::token_to_string(&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(diagnostics::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(diagnostics::DotDotDot { span });
    }

    fn err_larrow_operator(&self, span: Span) {
        self.dcx().emit_err(diagnostics::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<diagnostics::ForbiddenLetReason>,
    missing_let: Option<diagnostics::MaybeMissingLet>,
    comparison: Option<diagnostics::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 {
                        diagnostics::ForbiddenLetReason::NotSupportedOr(or_span) => {
                            self.parser.dcx().emit_err(diagnostics::OrInLetChain { span: or_span })
                        }
                        _ => {
                            let guar = self.parser.dcx().emit_err(
                                diagnostics::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(diagnostics::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(diagnostics::ForbiddenLetReason::NotSupportedOr(_)) =
                    self.forbid_let_reason =>
            {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason =
                    Some(diagnostics::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(diagnostics::ForbiddenLetReason::NotSupportedParentheses(_)) =
                    self.forbid_let_reason =>
            {
                let forbid_let_reason = self.forbid_let_reason;
                self.forbid_let_reason =
                    Some(diagnostics::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(diagnostics::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(diagnostics::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(diagnostics::MaybeMissingLet { span: rhs.span.shrink_to_lo() });
                }
                let comparison = self.comparison;
                self.comparison = Some(diagnostics::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::Move(_, _)
            | 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(diagnostics::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(diagnostics::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::DirectConstArg(_)
            | ExprKind::Dummy => {
                // These would forbid any let expressions they contain already.
            }
        }
        self.depth -= 1;
    }
}
