use std::borrow::Cow;
use std::mem;
use std::ops::Bound;

use ast::Label;
use rustc_ast as ast;
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
use rustc_ast::util::classify::{self, TrailingBrace};
use rustc_ast::visit::{Visitor, walk_expr};
use rustc_ast::{
    AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local,
    LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind,
};
use rustc_errors::{Applicability, Diag, PResult};
use rustc_span::{BytePos, ErrorGuaranteed, Ident, Span, kw, sym};
use thin_vec::{ThinVec, thin_vec};

use super::attr::InnerAttrForbiddenReason;
use super::diagnostics::AttemptLocalParseRecovery;
use super::pat::{PatternLocation, RecoverComma};
use super::path::PathStyle;
use super::{
    AllowConstBlockItems, AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser,
    Restrictions, SemiColonMode, Trailing, UsePreAttrPos,
};
use crate::diagnostics::{self, MalformedLoopLabel};
use crate::exp;

impl<'a> Parser<'a> {
    /// Parses a statement nonterminal, which has a peculiar syntax preserved for backward
    /// compatibility. The parsing stops just before trailing semicolons on everything but items.
    /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
    ///
    /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
    /// whether or not we have attributes.
    // Public for rustfmt usage.
    pub fn parse_stmt_nonterminal(&mut self, force_collect: ForceCollect) -> Option<Stmt> {
        match self.parse_stmt_without_recovery(false, force_collect, false) {
            Ok(stmt) => Some(stmt),
            Err(e) => {
                e.emit();
                self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
                None
            }
        }
    }

    /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
    /// whether or not we have attributes. If `force_full_expr` is true, parses the stmt without
    /// using `Restriction::STMT_EXPR`. Public for `cfg_eval` macro expansion.
    pub fn parse_stmt_without_recovery(
        &mut self,
        capture_semi: bool,
        force_collect: ForceCollect,
        force_full_expr: bool,
    ) -> PResult<'a, Stmt> {
        self.current_closure.take();

        let pre_attr_pos = self.collect_pos();
        let attrs = self.parse_outer_attributes()?;
        let lo = self.token.span;

        if let Some(mut stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| {
            this.parse_stmt_without_recovery(false, ForceCollect::Yes, false)
        }) {
            stmt.visit_attrs(|stmt_attrs| {
                attrs.prepend_to_nt_inner(stmt_attrs);
            });
            return Ok(stmt);
        }

        if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
            self.bump();
            let mut_let_span = lo.to(self.token.span);
            self.dcx().emit_err(diagnostics::InvalidVariableDeclaration {
                span: mut_let_span,
                sub: diagnostics::InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
            });
        }

        let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) {
            self.collect_tokens(None, attrs, force_collect, |this, attrs| {
                let super_span = this.token.span;
                this.expect_keyword(exp!(Super))?;
                this.expect_keyword(exp!(Let))?;
                this.psess.gated_spans.gate(sym::super_let, super_span);
                let local = this.parse_local(Some(super_span), attrs)?;
                let trailing = Trailing::from(capture_semi && this.token == token::Semi);
                Ok((
                    this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
                    trailing,
                    UsePreAttrPos::No,
                ))
            })?
        } else if self.token.is_keyword(kw::Let) {
            self.collect_tokens(None, attrs, force_collect, |this, attrs| {
                this.expect_keyword(exp!(Let))?;
                let local = this.parse_local(None, attrs)?;
                let trailing = Trailing::from(capture_semi && this.token == token::Semi);
                Ok((
                    this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
                    trailing,
                    UsePreAttrPos::No,
                ))
            })?
        } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
            self.recover_stmt_local_after_let(
                lo,
                attrs,
                diagnostics::InvalidVariableDeclarationSub::MissingLet,
                force_collect,
            )?
        } else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
            self.bump(); // `auto`
            self.recover_stmt_local_after_let(
                lo,
                attrs,
                diagnostics::InvalidVariableDeclarationSub::UseLetNotAuto,
                force_collect,
            )?
        } else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
            self.bump(); // `var`
            self.recover_stmt_local_after_let(
                lo,
                attrs,
                diagnostics::InvalidVariableDeclarationSub::UseLetNotVar,
                force_collect,
            )?
        } else if self.check_path()
            && !self.token.is_qpath_start()
            && !self.is_path_start_item()
            && !self.is_builtin()
        {
            // We have avoided contextual keywords like `union`, items with `crate` visibility,
            // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
            // that starts like a path (1 token), but it fact not a path.
            // Also, we avoid stealing syntax from `parse_item_`.
            //
            // `UsePreAttrPos::Yes` here means the attribute belongs unconditionally to the
            // expression, not the statement. (But the statement attributes/tokens are obtained
            // from the expression anyway, because `Stmt` delegates `HasAttrs`/`HasTokens` to
            // the things within `StmtKind`.)
            let stmt = self.collect_tokens(
                Some(pre_attr_pos),
                AttrWrapper::empty(),
                force_collect,
                |this, _empty_attrs| {
                    Ok((this.parse_stmt_path_start(lo, attrs)?, Trailing::No, UsePreAttrPos::Yes))
                },
            );
            match stmt {
                Ok(stmt) => stmt,
                Err(mut err) => {
                    self.suggest_add_missing_let_for_stmt(&mut err);
                    return Err(err);
                }
            }
        } else if let Some(item) = self.parse_item_common(
            attrs.clone(), // FIXME: unwanted clone of attrs
            false,
            true,
            FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true },
            force_collect,
            AllowConstBlockItems::No,
        )? {
            self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
        } else if self.eat(exp!(Semi)) {
            // Do not attempt to parse an expression if we're done here.
            self.error_outer_attrs(attrs)?;
            self.mk_stmt(lo, StmtKind::Empty)
        } else {
            if self.token == token::CloseBrace {
                self.error_outer_attrs(attrs.clone())?;
            }

            // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case
            // above.
            let restrictions =
                if force_full_expr { Restrictions::empty() } else { Restrictions::STMT_EXPR };
            let e = self.collect_tokens(
                Some(pre_attr_pos),
                AttrWrapper::empty(),
                force_collect,
                |this, _empty_attrs| {
                    let (expr, _) = this.parse_expr_res(restrictions, attrs)?;
                    Ok((expr, Trailing::No, UsePreAttrPos::Yes))
                },
            )?;
            if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(exp!(Else)) {
                let bl = self.parse_block()?;
                // Destructuring assignment ... else.
                // This is not allowed, but point it out in a nice way.
                self.dcx()
                    .emit_err(diagnostics::AssignmentElseNotAllowed { span: e.span.to(bl.span) });
            }
            self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
        };

        self.maybe_augment_stashed_expr_in_pats_with_suggestions(&stmt);
        Ok(stmt)
    }

    fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
        let stmt = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
            let path = this.parse_path(PathStyle::Expr)?;

            if this.eat(exp!(Bang)) {
                let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
                return Ok((
                    stmt_mac,
                    Trailing::from(this.token == token::Semi),
                    UsePreAttrPos::No,
                ));
            }

            let expr = if this.eat(exp!(OpenBrace)) {
                this.parse_expr_struct(None, path, true)?
            } else {
                let hi = this.prev_token.span;
                this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
            };

            let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
                this.parse_expr_dot_or_call_with(attrs, expr, lo)
            })?;
            // `DUMMY_SP` will get overwritten later in this function
            Ok((
                this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)),
                Trailing::No,
                UsePreAttrPos::No,
            ))
        })?;

        if let StmtKind::Expr(expr) = stmt.kind {
            // Perform this outside of the `collect_tokens` closure, since our
            // outer attributes do not apply to this part of the expression.
            let (expr, _) = self.with_res(Restrictions::STMT_EXPR, |this| {
                this.parse_expr_assoc_rest_with(Bound::Unbounded, true, expr)
            })?;
            Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
        } else {
            Ok(stmt)
        }
    }

    /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
    /// At this point, the `!` token after the path has already been eaten.
    fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResult<'a, Stmt> {
        let args = self.parse_delim_args()?;
        let hi = self.prev_token.span;

        let style = match args.delim {
            Delimiter::Brace => MacStmtStyle::Braces,
            _ => MacStmtStyle::NoBraces,
        };

        let mac = Box::new(MacCall { path, args });

        let kind = if (style == MacStmtStyle::Braces
            && !matches!(self.token.kind, token::Dot | token::Question))
            || matches!(
                self.token.kind,
                token::Semi
                    | token::Eof
                    | token::CloseInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Stmt))
            ) {
            StmtKind::MacCall(Box::new(MacCallStmt { mac, style, attrs, tokens: None }))
        } else {
            // Since none of the above applied, this is an expression statement macro.
            let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
            let e = self.maybe_recover_from_bad_qpath(e)?;
            let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?;
            let (e, _) = self.parse_expr_assoc_rest_with(Bound::Unbounded, false, e)?;
            StmtKind::Expr(e)
        };
        Ok(self.mk_stmt(lo.to(hi), kind))
    }

    /// Error on outer attributes in this context.
    /// Also error if the previous token was a doc comment.
    fn error_outer_attrs(&self, attrs: AttrWrapper) -> PResult<'a, ()> {
        if attrs.is_empty() {
            return Ok(());
        }
        let attrs = attrs.take_for_recovery(self.psess);
        let last = attrs.last().unwrap();
        Err(if last.is_doc_comment() {
            self.dcx().create_err(diagnostics::DocCommentDoesNotDocumentAnything {
                span: last.span,
                missing_comma: None,
            })
        } else {
            assert_eq!(last.style, AttrStyle::Outer);
            self.dcx().create_err(diagnostics::ExpectedStatementAfterOuterAttr { span: last.span })
        })
    }

    fn recover_stmt_local_after_let(
        &mut self,
        lo: Span,
        attrs: AttrWrapper,
        subdiagnostic: fn(Span) -> diagnostics::InvalidVariableDeclarationSub,
        force_collect: ForceCollect,
    ) -> PResult<'a, Stmt> {
        let stmt = self.collect_tokens(None, attrs, force_collect, |this, attrs| {
            let local = this.parse_local(None, attrs)?;
            // FIXME - maybe capture semicolon in recovery?
            Ok((
                this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)),
                Trailing::No,
                UsePreAttrPos::No,
            ))
        })?;
        self.dcx()
            .emit_err(diagnostics::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
        Ok(stmt)
    }

    /// Parses a local variable declaration.
    fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, Box<Local>> {
        let lo = super_.unwrap_or(self.prev_token.span);

        if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
            self.dcx()
                .emit_err(diagnostics::ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
            self.bump();
        }

        let (pat, colon) =
            self.parse_pat_before_ty(None, RecoverComma::Yes, PatternLocation::LetBinding)?;

        let (err, ty, colon_sp) = if colon {
            // Save the state of the parser before parsing type normally, in case there is a `:`
            // instead of an `=` typo.
            let parser_snapshot_before_type = self.clone();
            let colon_sp = self.prev_token.span;
            match self.parse_ty() {
                Ok(ty) => (None, Some(ty), Some(colon_sp)),
                Err(mut err) => {
                    err.span_label(
                        colon_sp,
                        format!(
                            "while parsing the type for {}",
                            pat.descr()
                                .map_or_else(|| "the binding".to_string(), |n| format!("`{n}`"))
                        ),
                    );
                    // we use noexpect here because we don't actually expect Eq to be here
                    // but we are still checking for it in order to be able to handle it if
                    // it is there
                    let err = if self.check_noexpect(&token::Eq) {
                        err.emit();
                        None
                    } else {
                        // Rewind to before attempting to parse the type and continue parsing.
                        let parser_snapshot_after_type =
                            mem::replace(self, parser_snapshot_before_type);
                        Some((parser_snapshot_after_type, colon_sp, err))
                    };
                    (err, None, Some(colon_sp))
                }
            }
        } else {
            (None, None, None)
        };
        let init = match (self.parse_initializer(err.is_some()), err) {
            (Ok(init), None) => {
                // init parsed, ty parsed
                init
            }
            (Ok(init), Some((_, colon_sp, mut err))) => {
                // init parsed, ty error
                // Could parse the type as if it were the initializer, it is likely there was a
                // typo in the code: `:` instead of `=`. Add suggestion and emit the error.
                err.span_suggestion_verbose(
                    colon_sp,
                    "use `=` if you meant to assign",
                    " =",
                    Applicability::MachineApplicable,
                );
                err.emit();
                // As this was parsed successfully, continue as if the code has been fixed for the
                // rest of the file. It will still fail due to the emitted error, but we avoid
                // extra noise.
                init
            }
            (Err(init_err), Some((snapshot, _, ty_err))) => {
                // init error, ty error
                init_err.cancel();
                // Couldn't parse the type nor the initializer, only raise the type error and
                // return to the parser state before parsing the type as the initializer.
                // let x: <parse_error>;
                *self = snapshot;
                return Err(ty_err);
            }
            (Err(err), None) => {
                // init error, ty parsed
                // Couldn't parse the initializer and we're not attempting to recover a failed
                // parse of the type, return the error.
                return Err(err);
            }
        };
        let kind = match init {
            None => LocalKind::Decl,
            Some(init) => {
                if self.eat_keyword(exp!(Else)) {
                    if self.token.is_keyword(kw::If) {
                        // `let...else if`. Emit the same error that `parse_block()` would,
                        // but explicitly point out that this pattern is not allowed.
                        let msg = "conditional `else if` is not supported for `let...else`";
                        return Err(self.error_block_no_opening_brace_msg(Cow::from(msg)));
                    }
                    let els = self.parse_block()?;
                    self.check_let_else_init_bool_expr(&init);
                    self.check_let_else_init_trailing_brace(&init);
                    LocalKind::InitElse(init, els)
                } else {
                    LocalKind::Init(init)
                }
            }
        };
        let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
        Ok(Box::new(ast::Local {
            super_,
            ty,
            pat,
            kind,
            id: DUMMY_NODE_ID,
            span: lo.to(hi),
            colon_sp,
            attrs,
            tokens: None,
        }))
    }

    fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
        if let ast::ExprKind::Binary(op, ..) = init.kind {
            if op.node.is_lazy() {
                self.dcx().emit_err(diagnostics::InvalidExpressionInLetElse {
                    span: init.span,
                    operator: op.node.as_str(),
                    sugg: diagnostics::WrapInParentheses::Expression {
                        left: init.span.shrink_to_lo(),
                        right: init.span.shrink_to_hi(),
                    },
                });
            }
        }
    }

    fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
        if let Some(trailing) = classify::expr_trailing_brace(init) {
            let (span, sugg) = match trailing {
                TrailingBrace::MacCall(mac) => (
                    mac.span(),
                    diagnostics::WrapInParentheses::MacroArgs {
                        left: mac.args.dspan.open,
                        right: mac.args.dspan.close,
                    },
                ),
                TrailingBrace::Expr(expr) => (
                    expr.span,
                    diagnostics::WrapInParentheses::Expression {
                        left: expr.span.shrink_to_lo(),
                        right: expr.span.shrink_to_hi(),
                    },
                ),
            };
            self.dcx().emit_err(diagnostics::InvalidCurlyInLetElse {
                span: span.with_lo(span.hi() - BytePos(1)),
                sugg,
            });
        }
    }

    /// Parses the RHS of a local variable declaration (e.g., `= 14;`).
    fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<Box<Expr>>> {
        let eq_consumed = match self.token.kind {
            token::PlusEq
            | token::MinusEq
            | token::StarEq
            | token::SlashEq
            | token::PercentEq
            | token::CaretEq
            | token::AndEq
            | token::OrEq
            | token::ShlEq
            | token::ShrEq => {
                // Recover `let x <op>= 1` as `let x = 1` We must not use `+ BytePos(1)` here
                // because `<op>` can be a multi-byte lookalike that was recovered, e.g. `➖=` (the
                // `➖` is a U+2796 Heavy Minus Sign Unicode Character) that was recovered as a
                // `-=`.
                let extra_op_span = self.psess.source_map().start_point(self.token.span);
                self.dcx().emit_err(diagnostics::CompoundAssignmentExpressionInLet {
                    span: self.token.span,
                    suggestion: extra_op_span,
                });
                self.bump();
                true
            }
            _ => self.eat(exp!(Eq)),
        };

        Ok(if eq_consumed || eq_optional { Some(self.parse_expr()?) } else { None })
    }

    /// Parses a block. No inner attributes are allowed.
    pub fn parse_block(&mut self) -> PResult<'a, Box<Block>> {
        let (attrs, block) = self.parse_inner_attrs_and_block(None)?;
        if let [.., last] = &*attrs {
            let suggest_to_outer = match &last.kind {
                ast::AttrKind::Normal(attr) => attr.item.is_valid_for_outer_style(),
                _ => false,
            };
            self.error_on_forbidden_inner_attr(
                last.span,
                super::attr::InnerAttrPolicy::Forbidden(Some(
                    InnerAttrForbiddenReason::InCodeBlock,
                )),
                suggest_to_outer,
            );
        }
        Ok(block)
    }

    fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> {
        let prev = self.prev_token.span;
        let sp = self.token.span;
        let mut err = self.dcx().struct_span_err(sp, msg);
        self.label_expected_raw_ref(&mut err);
        err.span_label(sp, "expected `{`");
        if self.token == token::CloseBrace {
            return err;
        }

        let do_not_suggest_help = self.token.is_keyword(kw::In)
            || self.token == token::Colon
            || self.prev_token.is_keyword(kw::Raw);

        // Check to see if the user has written something like
        //
        //    if (cond)
        //      bar;
        //
        // which is valid in other languages, but not Rust.
        match self.parse_stmt_without_recovery(false, ForceCollect::No, false) {
            // If the next token is an open brace, e.g., we have:
            //
            //     if expr other_expr {
            //        ^    ^          ^- lookahead(1) is a brace
            //        |    |- current token is not "else"
            //        |- (statement we just parsed)
            //
            // the place-inside-a-block suggestion would be more likely wrong than right.
            //
            // FIXME(compiler-errors): this should probably parse an arbitrary expr and not
            // just lookahead one token, so we can see if there's a brace after _that_,
            // since we want to protect against:
            //     `if 1 1 + 1 {` being suggested as  `if { 1 } 1 + 1 {`
            //                                            +   +
            Ok(_)
                if (!self.token.is_keyword(kw::Else)
                    && self.look_ahead(1, |t| t == &token::OpenBrace))
                    || do_not_suggest_help => {}
            // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
            Ok(Stmt { kind: StmtKind::Empty, .. }) => {}
            Ok(stmt) => {
                let stmt_own_line = self.psess.source_map().is_line_before_span_empty(sp);
                let stmt_span = if stmt_own_line && self.eat(exp!(Semi)) {
                    // Expand the span to include the semicolon.
                    stmt.span.with_hi(self.prev_token.span.hi())
                } else {
                    stmt.span
                };
                self.suggest_fixes_misparsed_for_loop_head(
                    &mut err,
                    prev.between(sp),
                    stmt_span,
                    &stmt.kind,
                );
            }
            Err(e) => {
                e.delay_as_bug();
            }
        }
        err
    }

    fn suggest_fixes_misparsed_for_loop_head(
        &self,
        e: &mut Diag<'_>,
        between: Span,
        stmt_span: Span,
        stmt_kind: &StmtKind,
    ) {
        match (&self.token.kind, &stmt_kind) {
            (token::OpenBrace, StmtKind::Expr(expr)) if let ExprKind::Call(..) = expr.kind => {
                // for _ in x y() {}
                e.span_suggestion_verbose(
                    between,
                    "you might have meant to write a method call",
                    ".".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
            (token::OpenBrace, StmtKind::Expr(expr)) if let ExprKind::Field(..) = expr.kind => {
                // for _ in x y.z {}
                e.span_suggestion_verbose(
                    between,
                    "you might have meant to write a field access",
                    ".".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
            (token::CloseBrace, StmtKind::Expr(expr))
                if let ExprKind::Struct(expr) = &expr.kind
                    && let None = expr.qself
                    && expr.path.segments.len() == 1 =>
            {
                // This is specific to "mistyped `if` condition followed by empty body"
                //
                // for _ in x y {}
                e.span_suggestion_verbose(
                    between,
                    "you might have meant to write a field access",
                    ".".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
            (token::OpenBrace, StmtKind::Expr(expr))
                if let ExprKind::Lit(lit) = expr.kind
                    && let None = lit.suffix
                    && let token::LitKind::Integer | token::LitKind::Float = lit.kind =>
            {
                // for _ in x 0 {}
                // for _ in x 0.0 {}
                e.span_suggestion_verbose(
                    between,
                    format!("you might have meant to write a field access"),
                    ".".to_string(),
                    Applicability::MaybeIncorrect,
                );
            }
            (token::OpenBrace, StmtKind::Expr(expr))
                if let ExprKind::Loop(..)
                | ExprKind::If(..)
                | ExprKind::While(..)
                | ExprKind::Match(..)
                | ExprKind::ForLoop { .. }
                | ExprKind::TryBlock(..)
                | ExprKind::Ret(..)
                | ExprKind::Closure(..)
                | ExprKind::Struct(..)
                | ExprKind::Try(..) = expr.kind =>
            {
                // These are more likely to have been meant as a block body.
                e.multipart_suggestion(
                    "you might have meant to write this as part of a block",
                    vec![
                        (stmt_span.shrink_to_lo(), "{ ".to_string()),
                        (stmt_span.shrink_to_hi(), " }".to_string()),
                    ],
                    // Speculative; has been misleading in the past (#46836).
                    Applicability::MaybeIncorrect,
                );
            }
            (token::OpenBrace, _) => {}
            (_, _) => {
                e.multipart_suggestion(
                    "you might have meant to write this as part of a block",
                    vec![
                        (stmt_span.shrink_to_lo(), "{ ".to_string()),
                        (stmt_span.shrink_to_hi(), " }".to_string()),
                    ],
                    // Speculative; has been misleading in the past (#46836).
                    Applicability::MaybeIncorrect,
                );
            }
        }
    }

    fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
        let tok = super::token_descr(&self.token);
        let msg = format!("expected `{{`, found {tok}");
        Err(self.error_block_no_opening_brace_msg(Cow::from(msg)))
    }

    /// Parses a block. Inner attributes are allowed, block labels are not.
    ///
    /// If `loop_header` is `Some` and an unexpected block label is encountered,
    /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed.
    pub(super) fn parse_inner_attrs_and_block(
        &mut self,
        loop_header: Option<Span>,
    ) -> PResult<'a, (AttrVec, Box<Block>)> {
        self.parse_block_common(self.token.span, BlockCheckMode::Default, loop_header)
    }

    /// Parses a block. Inner attributes are allowed, block labels are not.
    ///
    /// If `loop_header` is `Some` and an unexpected block label is encountered,
    /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed.
    pub(super) fn parse_block_common(
        &mut self,
        lo: Span,
        blk_mode: BlockCheckMode,
        loop_header: Option<Span>,
    ) -> PResult<'a, (AttrVec, Box<Block>)> {
        if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) {
            return Ok((AttrVec::new(), block));
        }

        let maybe_ident = self.prev_token;
        self.maybe_recover_unexpected_block_label(loop_header);
        if !self.eat(exp!(OpenBrace)) {
            return self.error_block_no_opening_brace();
        }

        let attrs = self.parse_inner_attributes()?;
        let tail = match self.maybe_suggest_struct_literal(lo, blk_mode, maybe_ident) {
            Some(tail) => tail?,
            None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
        };
        Ok((attrs, tail))
    }

    /// Parses the rest of a block expression or function body.
    /// Precondition: already parsed the '{'.
    pub fn parse_block_tail(
        &mut self,
        lo: Span,
        s: BlockCheckMode,
        recover: AttemptLocalParseRecovery,
    ) -> PResult<'a, Box<Block>> {
        let mut stmts = ThinVec::new();
        let mut snapshot = None;
        while !self.eat(exp!(CloseBrace)) {
            if self.token == token::Eof {
                break;
            }
            if self.is_vcs_conflict_marker(&TokenKind::Shl, &TokenKind::Lt) {
                // Account for `<<<<<<<` diff markers. We can't proactively error here because
                // that can be a valid path start, so we snapshot and reparse only we've
                // encountered another parse error.
                snapshot = Some(self.create_snapshot_for_diagnostic());
            }
            let stmt = match self.parse_full_stmt(recover) {
                Err(mut err) if recover.yes() => {
                    if let Some(ref mut snapshot) = snapshot {
                        snapshot.recover_vcs_conflict_marker();
                    }
                    if self.token == token::Colon {
                        // if a previous and next token of the current one is
                        // integer literal (e.g. `1:42`), it's likely a range
                        // expression for Pythonistas and we can suggest so.
                        if self.prev_token.is_integer_lit()
                            && self.may_recover()
                            && self.look_ahead(1, |token| token.is_integer_lit())
                        {
                            // FIXME(hkmatsumoto): Might be better to trigger
                            // this only when parsing an index expression.
                            err.span_suggestion_verbose(
                                self.token.span,
                                "you might have meant a range expression",
                                "..",
                                Applicability::MaybeIncorrect,
                            );
                        } else {
                            // if next token is following a colon, it's likely a path
                            // and we can suggest a path separator
                            self.bump();
                            if self.token.span.lo() == self.prev_token.span.hi() {
                                err.span_suggestion_verbose(
                                    self.prev_token.span,
                                    "maybe write a path separator here",
                                    "::",
                                    Applicability::MaybeIncorrect,
                                );
                            }
                        }
                    }

                    let guar = err.emit();
                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
                    self.mk_stmt_err(self.token.span, guar)
                }
                Ok(stmt) => stmt,
                Err(err) => return Err(err),
            };
            stmts.push(stmt);
        }
        Ok(self.mk_block(stmts, s, lo.to(self.prev_token.span)))
    }

    fn recover_missing_let_else(&mut self, err: &mut Diag<'_>, pat: &ast::Pat, stmt_span: Span) {
        if self.token.kind != token::OpenBrace {
            return;
        }
        match pat.kind {
            ast::PatKind::Ident(..) | ast::PatKind::Missing | ast::PatKind::Wild => {
                // Not if let or let else
                return;
            }
            _ => {}
        }
        let snapshot = self.create_snapshot_for_diagnostic();
        let block_span = self.token.span;
        let (if_let, let_else) = match self.parse_block() {
            Ok(block) => {
                let mut idents = vec![];
                pat.walk(&mut |pat: &ast::Pat| {
                    if let ast::PatKind::Ident(_, ident, _) = pat.kind {
                        idents.push(ident);
                    }
                    true
                });

                struct IdentFinder {
                    idents: Vec<Ident>,
                    /// If a block references one of the bindings introduced by the let pattern,
                    /// we likely meant to use `if let`.
                    /// This is pre-expansion, so if we encounter
                    /// `let Some(x) = foo() { println!("{x}") }` we won't find it.
                    references_ident: bool = false,
                    /// If a block has a `return`, then we know with high certainty that it was
                    /// meant to be let-else.
                    has_return: bool = false,
                }

                impl<'a> Visitor<'a> for IdentFinder {
                    fn visit_ident(&mut self, ident: &Ident) {
                        for i in &self.idents {
                            if ident.name == i.name {
                                self.references_ident = true;
                            }
                        }
                    }
                    fn visit_expr(&mut self, node: &'a Expr) {
                        if let ExprKind::Ret(..) = node.kind {
                            self.has_return = true;
                        }
                        walk_expr(self, node);
                    }
                }

                // Collect all bindings in pattern and see if they appear in the block. Likely meant
                // to write `if let`. See if the block has a return. Likely meant to write
                // `let else`.
                let mut visitor = IdentFinder { idents, .. };
                visitor.visit_block(&block);

                (visitor.references_ident, visitor.has_return)
            }
            Err(e) => {
                e.cancel();
                self.restore_snapshot(snapshot);
                (false, false)
            }
        };

        let mut alternatively = "";
        if if_let || !let_else {
            alternatively = "alternatively, ";
            err.span_suggestion_verbose(
                stmt_span.shrink_to_lo(),
                "you might have meant to use `if let`",
                "if ".to_string(),
                if if_let {
                    Applicability::MachineApplicable
                } else {
                    Applicability::MaybeIncorrect
                },
            );
        }
        if let_else || !if_let {
            err.span_suggestion_verbose(
                block_span.shrink_to_lo(),
                format!("{alternatively}you might have meant to use `let...else`"),
                "else ".to_string(),
                if let_else {
                    Applicability::MachineApplicable
                } else {
                    Applicability::MaybeIncorrect
                },
            );
        }
    }

    fn recover_missing_dot(&mut self, err: &mut Diag<'_>) {
        let Some((ident, _)) = self.token.ident() else {
            return;
        };
        if let Some(c) = ident.name.as_str().chars().next()
            && c.is_uppercase()
        {
            return;
        }
        if self.token.is_reserved_ident() && !self.token.is_ident_named(kw::Await) {
            return;
        }
        if self.prev_token.is_reserved_ident() && self.prev_token.is_ident_named(kw::Await) {
            // Likely `foo.await bar`
        } else if self.prev_token.is_non_reserved_ident() {
            // Likely `foo bar`
        } else if self.prev_token.kind == token::Question {
            // `foo? bar`
        } else if self.prev_token.kind == token::CloseParen {
            // `foo() bar`
        } else {
            return;
        }
        if self.token.span == self.prev_token.span {
            // Account for syntax errors in proc-macros.
            return;
        }
        if self.look_ahead(1, |t| [token::Semi, token::Question, token::Dot].contains(&t.kind)) {
            err.span_suggestion_verbose(
                self.prev_token.span.between(self.token.span),
                "you might have meant to write a field access",
                ".".to_string(),
                Applicability::MaybeIncorrect,
            );
        }
        if self.look_ahead(1, |t| t.kind == token::OpenParen) {
            err.span_suggestion_verbose(
                self.prev_token.span.between(self.token.span),
                "you might have meant to write a method call",
                ".".to_string(),
                Applicability::MaybeIncorrect,
            );
        }
    }

    fn try_recover_let_missing_semi(&mut self, local: &mut Local) -> Option<ErrorGuaranteed> {
        let expr = match &mut local.kind {
            LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => expr,
            LocalKind::Decl => return None,
        };
        if let Some((span, guar)) =
            self.missing_semi_from_binop("`let` binding", expr, Some(local.span.shrink_to_lo()))
        {
            self.fn_body_missing_semi_guar = Some(guar);
            *expr = self.mk_expr(span, ExprKind::Err(guar));
            return Some(guar);
        }
        None
    }

    /// Parses a statement, including the trailing semicolon.
    pub fn parse_full_stmt(&mut self, recover: AttemptLocalParseRecovery) -> PResult<'a, Stmt> {
        // Skip looking for a trailing semicolon when we have a metavar seq.
        if let Some(stmt) = self.eat_metavar_seq(MetaVarKind::Stmt, |this| {
            // Why pass `true` for `force_full_expr`? Statement expressions are less expressive
            // than "full" expressions, due to the `STMT_EXPR` restriction, and sometimes need
            // parentheses. E.g. the "full" expression `match paren_around_match {} | true` when
            // used in statement context must be written `(match paren_around_match {} | true)`.
            // However, if the expression we are parsing in this statement context was pasted by a
            // declarative macro, it may have come from a "full" expression context, and lack
            // these parentheses. So we lift the `STMT_EXPR` restriction to ensure the statement
            // will reparse successfully.
            this.parse_stmt_without_recovery(false, ForceCollect::No, true)
        }) {
            return Ok(stmt);
        }

        let mut stmt = self.parse_stmt_without_recovery(true, ForceCollect::No, false)?;

        let mut eat_semi = true;
        let mut add_semi_to_stmt = false;

        match &mut stmt.kind {
            // Expression without semicolon.
            StmtKind::Expr(expr)
                if classify::expr_requires_semi_to_be_stmt(expr)
                    && !expr.attrs.is_empty()
                    && !matches!(self.token.kind, token::Eof | token::Semi | token::CloseBrace) =>
            {
                // The user has written `#[attr] expr` which is unsupported. (#106020)
                let guar = self.attr_on_non_tail_expr(&expr);
                // We already emitted an error, so don't emit another type error
                let sp = expr.span.to(self.prev_token.span);
                *expr = self.mk_expr_err(sp, guar);
            }

            // Expression without semicolon.
            StmtKind::Expr(expr)
                if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) =>
            {
                // Just check for errors and recover; do not eat semicolon yet.

                let expect_result =
                    if let Err(e) = self.maybe_recover_from_ternary_operator(Some(expr.span)) {
                        Err(e)
                    } else {
                        self.expect_one_of(&[], &[exp!(Semi), exp!(CloseBrace)])
                    };

                // Try to both emit a better diagnostic, and avoid further errors by replacing
                // the `expr` with `ExprKind::Err`.
                let replace_with_err = 'break_recover: {
                    match expect_result {
                        Ok(Recovered::No) => None,
                        Ok(Recovered::Yes(guar)) => {
                            // Skip type error to avoid extra errors.
                            Some(guar)
                        }
                        Err(e) => {
                            if self.recover_colon_as_semi() {
                                // recover_colon_as_semi has already emitted a nicer error.
                                e.delay_as_bug();
                                add_semi_to_stmt = true;
                                eat_semi = false;

                                break 'break_recover None;
                            }

                            match &expr.kind {
                                ExprKind::Path(None, ast::Path { segments, .. })
                                    if let [segment] = segments.as_slice() =>
                                {
                                    if self.token == token::Colon
                                        && self.look_ahead(1, |token| {
                                            token.is_metavar_block()
                                                || matches!(
                                                    token.kind,
                                                    token::Ident(
                                                        kw::For | kw::Loop | kw::While,
                                                        token::IdentIsRaw::No
                                                    ) | token::OpenBrace
                                                )
                                        })
                                    {
                                        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(labeled_expr) => {
                                                e.cancel();
                                                self.dcx().emit_err(MalformedLoopLabel {
                                                    span: label.ident.span,
                                                    suggestion: label.ident.span.shrink_to_lo(),
                                                });
                                                *expr = labeled_expr;
                                                break 'break_recover None;
                                            }
                                            Err(err) => {
                                                err.cancel();
                                                self.restore_snapshot(snapshot);
                                            }
                                        }
                                    }
                                }
                                _ => {}
                            }

                            let res =
                                self.check_mistyped_turbofish_with_multiple_type_params(e, expr);

                            Some(if recover.no() {
                                res?
                            } else {
                                res.unwrap_or_else(|mut e| {
                                    self.recover_missing_dot(&mut e);
                                    let guar = e.emit();
                                    self.recover_stmt();
                                    guar
                                })
                            })
                        }
                    }
                };

                if let Some(guar) = replace_with_err {
                    // We already emitted an error, so don't emit another type error
                    let sp = expr.span.to(self.prev_token.span);
                    *expr = self.mk_expr_err(sp, guar);
                }
            }
            StmtKind::Expr(_) | StmtKind::MacCall(_) => {}
            StmtKind::Let(local) => {
                if self.try_recover_let_missing_semi(local).is_some() {
                    return Ok(stmt);
                }
                if let Err(mut e) = self.expect_semi() {
                    // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
                    match &mut local.kind {
                        LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
                            self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
                                .map_err(|mut e| {
                                    self.recover_missing_dot(&mut e);
                                    self.recover_missing_let_else(&mut e, &local.pat, stmt.span);
                                    e
                                })?;
                            // We found `foo<bar, baz>`, have we fully recovered?
                            self.expect_semi()?;
                        }
                        LocalKind::Decl => {
                            if let Some(colon_sp) = local.colon_sp {
                                e.span_label(
                                    colon_sp,
                                    format!(
                                        "while parsing the type for {}",
                                        local.pat.descr().map_or_else(
                                            || "the binding".to_string(),
                                            |n| format!("`{n}`")
                                        )
                                    ),
                                );
                                let suggest_eq = if self.token == token::Dot
                                    && let _ = self.bump()
                                    && let mut snapshot = self.create_snapshot_for_diagnostic()
                                    && let Ok(_) = snapshot
                                        .parse_dot_suffix_expr(
                                            colon_sp,
                                            self.mk_expr_err(
                                                colon_sp,
                                                self.dcx().delayed_bug(
                                                    "error during `:` -> `=` recovery",
                                                ),
                                            ),
                                        )
                                        .map_err(Diag::cancel)
                                {
                                    true
                                } else if let Some(op) = self.check_assoc_op()
                                    && op.node.can_continue_expr_unambiguously()
                                {
                                    true
                                } else {
                                    false
                                };
                                if suggest_eq && let Some(ty) = &local.ty {
                                    e.span_suggestion_verbose(
                                        local.pat.span.between(ty.span),
                                        "use `=` if you meant to assign",
                                        " = ",
                                        Applicability::MaybeIncorrect,
                                    );
                                }
                            }
                            return Err(e);
                        }
                    }
                }
                eat_semi = false;
            }
            StmtKind::Empty | StmtKind::Item(_) | StmtKind::Semi(_) => eat_semi = false,
        }

        if add_semi_to_stmt || (eat_semi && self.eat(exp!(Semi))) {
            stmt = stmt.add_trailing_semicolon();
        }

        stmt.span = stmt.span.to(self.prev_token.span);
        Ok(stmt)
    }

    pub(super) fn mk_block(
        &self,
        stmts: ThinVec<Stmt>,
        rules: BlockCheckMode,
        span: Span,
    ) -> Box<Block> {
        Box::new(Block { stmts, id: DUMMY_NODE_ID, rules, span })
    }

    pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
        Stmt { id: DUMMY_NODE_ID, kind, span }
    }

    pub(super) fn mk_stmt_err(&self, span: Span, guar: ErrorGuaranteed) -> Stmt {
        self.mk_stmt(span, StmtKind::Expr(self.mk_expr_err(span, guar)))
    }

    pub(super) fn mk_block_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Block> {
        self.mk_block(thin_vec![self.mk_stmt_err(span, guar)], BlockCheckMode::Default, span)
    }
}
