//! Type checking expressions.
//!
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.

use crate::cast;
use crate::coercion::CoerceMany;
use crate::coercion::DynamicCoerceMany;
use crate::errors::ReturnLikeStatementKind;
use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
    FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
    YieldExprOutsideOfCoroutine,
};
use crate::fatally_break_rust;
use crate::method::SelfSource;
use crate::type_error_struct;
use crate::CoroutineTypes;
use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
use crate::{
    report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
    TupleArgumentsFlag::DontTupleArguments,
};
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{
    codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey,
    Subdiagnostic,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
use rustc_infer::infer;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::InferOk;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCauseCode};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
    pub fn check_expr_has_type_or_error(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected_ty: Ty<'tcx>,
        extend_err: impl FnOnce(&mut Diag<'_>),
    ) -> Ty<'tcx> {
        let mut ty = self.check_expr_with_expectation(expr, ExpectHasType(expected_ty));

        // While we don't allow *arbitrary* coercions here, we *do* allow
        // coercions from ! to `expected`.
        if ty.is_never() {
            if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
                let reported = self.dcx().span_delayed_bug(
                    expr.span,
                    "expression with never type wound up being adjusted",
                );
                return Ty::new_error(self.tcx(), reported);
            }

            let adj_ty = self.next_ty_var(expr.span);
            self.apply_adjustments(
                expr,
                vec![Adjustment { kind: Adjust::NeverToAny, target: adj_ty }],
            );
            ty = adj_ty;
        }

        if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
            let _ = self.emit_type_mismatch_suggestions(
                &mut err,
                expr.peel_drop_temps(),
                ty,
                expected_ty,
                None,
                None,
            );
            extend_err(&mut err);
            err.emit();
        }
        ty
    }

    pub(super) fn check_expr_coercible_to_type(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Ty<'tcx>,
        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
    ) -> Ty<'tcx> {
        let ty = self.check_expr_with_hint(expr, expected);
        // checks don't need two phase
        self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No)
    }

    pub(super) fn check_expr_with_hint(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Ty<'tcx>,
    ) -> Ty<'tcx> {
        self.check_expr_with_expectation(expr, ExpectHasType(expected))
    }

    fn check_expr_with_expectation_and_needs(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
        needs: Needs,
    ) -> Ty<'tcx> {
        let ty = self.check_expr_with_expectation(expr, expected);

        // If the expression is used in a place whether mutable place is required
        // e.g. LHS of assignment, perform the conversion.
        if let Needs::MutPlace = needs {
            self.convert_place_derefs_to_mutable(expr);
        }

        ty
    }

    pub(super) fn check_expr(&self, expr: &'tcx hir::Expr<'tcx>) -> Ty<'tcx> {
        self.check_expr_with_expectation(expr, NoExpectation)
    }

    pub(super) fn check_expr_with_needs(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        needs: Needs,
    ) -> Ty<'tcx> {
        self.check_expr_with_expectation_and_needs(expr, NoExpectation, needs)
    }

    /// Invariant:
    /// If an expression has any sub-expressions that result in a type error,
    /// inspecting that expression's type with `ty.references_error()` will return
    /// true. Likewise, if an expression is known to diverge, inspecting its
    /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
    /// strict, _|_ can appear in the type of an expression that does not,
    /// itself, diverge: for example, fn() -> _|_.)
    /// Note that inspecting a type's structure *directly* may expose the fact
    /// that there are actually multiple representations for `Error`, so avoid
    /// that when err needs to be handled differently.
    #[instrument(skip(self, expr), level = "debug")]
    pub(super) fn check_expr_with_expectation(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        self.check_expr_with_expectation_and_args(expr, expected, &[], None)
    }

    /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
    /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
    pub(super) fn check_expr_with_expectation_and_args(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
        args: &'tcx [hir::Expr<'tcx>],
        call: Option<&'tcx hir::Expr<'tcx>>,
    ) -> Ty<'tcx> {
        if self.tcx().sess.verbose_internals() {
            // make this code only run with -Zverbose-internals because it is probably slow
            if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
                if !lint_str.contains('\n') {
                    debug!("expr text: {lint_str}");
                } else {
                    let mut lines = lint_str.lines();
                    if let Some(line0) = lines.next() {
                        let remaining_lines = lines.count();
                        debug!("expr text: {line0}");
                        debug!("expr text: ...(and {remaining_lines} more lines)");
                    }
                }
            }
        }

        // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
        // without the final expr (e.g. `try { return; }`). We don't want to generate an
        // unreachable_code lint for it since warnings for autogenerated code are confusing.
        let is_try_block_generated_unit_expr = match expr.kind {
            ExprKind::Call(_, [arg]) => {
                expr.span.is_desugaring(DesugaringKind::TryBlock)
                    && arg.span.is_desugaring(DesugaringKind::TryBlock)
            }
            _ => false,
        };

        // Warn for expressions after diverging siblings.
        if !is_try_block_generated_unit_expr {
            self.warn_if_unreachable(expr.hir_id, expr.span, "expression");
        }

        // Whether a past expression diverges doesn't affect typechecking of this expression, so we
        // reset `diverges` while checking `expr`.
        let old_diverges = self.diverges.replace(Diverges::Maybe);

        if self.is_whole_body.replace(false) {
            // If this expression is the whole body and the function diverges because of its
            // arguments, we check this here to ensure the body is considered to diverge.
            self.diverges.set(self.function_diverges_because_of_empty_arguments.get())
        };

        let ty = ensure_sufficient_stack(|| match &expr.kind {
            hir::ExprKind::Path(
                qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),
            ) => self.check_expr_path(qpath, expr, args, call),
            _ => self.check_expr_kind(expr, expected),
        });
        let ty = self.resolve_vars_if_possible(ty);

        // Warn for non-block expressions with diverging children.
        match expr.kind {
            ExprKind::Block(..)
            | ExprKind::If(..)
            | ExprKind::Let(..)
            | ExprKind::Loop(..)
            | ExprKind::Match(..) => {}
            // If `expr` is a result of desugaring the try block and is an ok-wrapped
            // diverging expression (e.g. it arose from desugaring of `try { return }`),
            // we skip issuing a warning because it is autogenerated code.
            ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {}
            ExprKind::Call(callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"),
            ExprKind::MethodCall(segment, ..) => {
                self.warn_if_unreachable(expr.hir_id, segment.ident.span, "call")
            }
            _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
        }

        // Any expression that produces a value of type `!` must have diverged
        if ty.is_never() {
            self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
        }

        // Record the type, which applies it effects.
        // We need to do this after the warning above, so that
        // we don't warn for the diverging expression itself.
        self.write_ty(expr.hir_id, ty);

        // Combine the diverging and has_error flags.
        self.diverges.set(self.diverges.get() | old_diverges);

        debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id));
        debug!("... {:?}, expected is {:?}", ty, expected);

        ty
    }

    #[instrument(skip(self, expr), level = "debug")]
    fn check_expr_kind(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        trace!("expr={:#?}", expr);

        let tcx = self.tcx;
        match expr.kind {
            ExprKind::Lit(ref lit) => self.check_lit(lit, expected),
            ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected),
            ExprKind::Assign(lhs, rhs, span) => {
                self.check_expr_assign(expr, expected, lhs, rhs, span)
            }
            ExprKind::AssignOp(op, lhs, rhs) => {
                self.check_binop_assign(expr, op, lhs, rhs, expected)
            }
            ExprKind::Unary(unop, oprnd) => self.check_expr_unary(unop, oprnd, expected, expr),
            ExprKind::AddrOf(kind, mutbl, oprnd) => {
                self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
            }
            ExprKind::Path(QPath::LangItem(lang_item, _)) => {
                self.check_lang_item_path(lang_item, expr)
            }
            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[], None),
            ExprKind::InlineAsm(asm) => {
                // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
                self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
                self.check_expr_asm(asm)
            }
            ExprKind::OffsetOf(container, fields) => self.check_offset_of(container, fields, expr),
            ExprKind::Break(destination, ref expr_opt) => {
                self.check_expr_break(destination, expr_opt.as_deref(), expr)
            }
            ExprKind::Continue(destination) => {
                if destination.target_id.is_ok() {
                    tcx.types.never
                } else {
                    // There was an error; make type-check fail.
                    Ty::new_misc_error(tcx)
                }
            }
            ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
            ExprKind::Become(call) => self.check_expr_become(call, expr),
            ExprKind::Let(let_expr) => self.check_expr_let(let_expr, expr.hir_id),
            ExprKind::Loop(body, _, source, _) => {
                self.check_expr_loop(body, source, expected, expr)
            }
            ExprKind::Match(discrim, arms, match_src) => {
                self.check_match(expr, discrim, arms, expected, match_src)
            }
            ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
            ExprKind::Block(body, _) => self.check_block_with_expected(body, expected),
            ExprKind::Call(callee, args) => self.check_call(expr, callee, args, expected),
            ExprKind::MethodCall(segment, receiver, args, _) => {
                self.check_method_call(expr, segment, receiver, args, expected)
            }
            ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
            ExprKind::Type(e, t) => {
                let ascribed_ty = self.lower_ty_saving_user_provided_ty(t);
                let ty = self.check_expr_with_hint(e, ascribed_ty);
                self.demand_eqtype(e.span, ascribed_ty, ty);
                ascribed_ty
            }
            ExprKind::If(cond, then_expr, opt_else_expr) => {
                self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected)
            }
            ExprKind::DropTemps(e) => self.check_expr_with_expectation(e, expected),
            ExprKind::Array(args) => self.check_expr_array(args, expected, expr),
            ExprKind::ConstBlock(ref block) => self.check_expr_const_block(block, expected),
            ExprKind::Repeat(element, ref count) => {
                self.check_expr_repeat(element, count, expected, expr)
            }
            ExprKind::Tup(elts) => self.check_expr_tuple(elts, expected, expr),
            ExprKind::Struct(qpath, fields, ref base_expr) => {
                self.check_expr_struct(expr, expected, qpath, fields, base_expr)
            }
            ExprKind::Field(base, field) => self.check_field(expr, base, field, expected),
            ExprKind::Index(base, idx, brackets_span) => {
                self.check_expr_index(base, idx, expr, brackets_span)
            }
            ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
            hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar),
        }
    }

    fn check_expr_unary(
        &self,
        unop: hir::UnOp,
        oprnd: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let tcx = self.tcx;
        let expected_inner = match unop {
            hir::UnOp::Not | hir::UnOp::Neg => expected,
            hir::UnOp::Deref => NoExpectation,
        };
        let mut oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner);

        if !oprnd_t.references_error() {
            oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);
            match unop {
                hir::UnOp::Deref => {
                    if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) {
                        oprnd_t = ty;
                    } else {
                        let mut err = type_error_struct!(
                            self.dcx(),
                            expr.span,
                            oprnd_t,
                            E0614,
                            "type `{oprnd_t}` cannot be dereferenced",
                        );
                        let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);
                        if let Some(sp) =
                            tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp)
                        {
                            err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                        }
                        oprnd_t = Ty::new_error(tcx, err.emit());
                    }
                }
                hir::UnOp::Not => {
                    let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
                    // If it's builtin, we can reuse the type, this helps inference.
                    if !(oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool) {
                        oprnd_t = result;
                    }
                }
                hir::UnOp::Neg => {
                    let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
                    // If it's builtin, we can reuse the type, this helps inference.
                    if !oprnd_t.is_numeric() {
                        oprnd_t = result;
                    }
                }
            }
        }
        oprnd_t
    }

    fn check_expr_addr_of(
        &self,
        kind: hir::BorrowKind,
        mutbl: hir::Mutability,
        oprnd: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
            match ty.kind() {
                ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
                    if oprnd.is_syntactic_place_expr() {
                        // Places may legitimately have unsized types.
                        // For example, dereferences of a fat pointer and
                        // the last field of a struct can be unsized.
                        ExpectHasType(*ty)
                    } else {
                        Expectation::rvalue_hint(self, *ty)
                    }
                }
                _ => NoExpectation,
            }
        });
        let ty =
            self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));

        match kind {
            _ if ty.references_error() => Ty::new_misc_error(self.tcx),
            hir::BorrowKind::Raw => {
                self.check_named_place_expr(oprnd);
                Ty::new_ptr(self.tcx, ty, mutbl)
            }
            hir::BorrowKind::Ref => {
                // Note: at this point, we cannot say what the best lifetime
                // is to use for resulting pointer. We want to use the
                // shortest lifetime possible so as to avoid spurious borrowck
                // errors. Moreover, the longest lifetime will depend on the
                // precise details of the value whose address is being taken
                // (and how long it is valid), which we don't know yet until
                // type inference is complete.
                //
                // Therefore, here we simply generate a region variable. The
                // region inferencer will then select a suitable value.
                // Finally, borrowck will infer the value of the region again,
                // this time with enough precision to check that the value
                // whose address was taken can actually be made to live as long
                // as it needs to live.
                let region = self.next_region_var(infer::AddrOfRegion(expr.span));
                Ty::new_ref(self.tcx, region, ty, mutbl)
            }
        }
    }

    /// Does this expression refer to a place that either:
    /// * Is based on a local or static.
    /// * Contains a dereference
    /// Note that the adjustments for the children of `expr` should already
    /// have been resolved.
    fn check_named_place_expr(&self, oprnd: &'tcx hir::Expr<'tcx>) {
        let is_named = oprnd.is_place_expr(|base| {
            // Allow raw borrows if there are any deref adjustments.
            //
            // const VAL: (i32,) = (0,);
            // const REF: &(i32,) = &(0,);
            //
            // &raw const VAL.0;            // ERROR
            // &raw const REF.0;            // OK, same as &raw const (*REF).0;
            //
            // This is maybe too permissive, since it allows
            // `let u = &raw const Box::new((1,)).0`, which creates an
            // immediately dangling raw pointer.
            self.typeck_results
                .borrow()
                .adjustments()
                .get(base.hir_id)
                .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
        });
        if !is_named {
            self.dcx().emit_err(AddressOfTemporaryTaken { span: oprnd.span });
        }
    }

    fn check_lang_item_path(
        &self,
        lang_item: hir::LangItem,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
    }

    pub(crate) fn check_expr_path(
        &self,
        qpath: &'tcx hir::QPath<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
        args: &'tcx [hir::Expr<'tcx>],
        call: Option<&'tcx hir::Expr<'tcx>>,
    ) -> Ty<'tcx> {
        let tcx = self.tcx;
        let (res, opt_ty, segs) =
            self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args));
        let ty = match res {
            Res::Err => {
                self.suggest_assoc_method_call(segs);
                let e =
                    self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
                self.set_tainted_by_errors(e);
                Ty::new_error(tcx, e)
            }
            Res::Def(DefKind::Variant, _) => {
                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
                Ty::new_error(tcx, e)
            }
            _ => {
                self.instantiate_value_path(
                    segs,
                    opt_ty,
                    res,
                    call.map_or(expr.span, |e| e.span),
                    expr.span,
                    expr.hir_id,
                )
                .0
            }
        };

        if let ty::FnDef(did, _) = *ty.kind() {
            let fn_sig = ty.fn_sig(tcx);

            if tcx.is_intrinsic(did, sym::transmute) {
                let Some(from) = fn_sig.inputs().skip_binder().get(0) else {
                    span_bug!(
                        tcx.def_span(did),
                        "intrinsic fn `transmute` defined with no parameters"
                    );
                };
                let to = fn_sig.output().skip_binder();
                // We defer the transmute to the end of typeck, once all inference vars have
                // been resolved or we errored. This is important as we can only check transmute
                // on concrete types, but the output type may not be known yet (it would only
                // be known if explicitly specified via turbofish).
                self.deferred_transmute_checks.borrow_mut().push((*from, to, expr.hir_id));
            }
            if !tcx.features().unsized_fn_params {
                // We want to remove some Sized bounds from std functions,
                // but don't want to expose the removal to stable Rust.
                // i.e., we don't want to allow
                //
                // ```rust
                // drop as fn(str);
                // ```
                //
                // to work in stable even if the Sized bound on `drop` is relaxed.
                for i in 0..fn_sig.inputs().skip_binder().len() {
                    // We just want to check sizedness, so instead of introducing
                    // placeholder lifetimes with probing, we just replace higher lifetimes
                    // with fresh vars.
                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
                    let input = self.instantiate_binder_with_fresh_vars(
                        span,
                        infer::BoundRegionConversionTime::FnCall,
                        fn_sig.input(i),
                    );
                    self.require_type_is_sized_deferred(
                        input,
                        span,
                        ObligationCauseCode::SizedArgumentType(None),
                    );
                }
            }
            // Here we want to prevent struct constructors from returning unsized types.
            // There were two cases this happened: fn pointer coercion in stable
            // and usual function call in presence of unsized_locals.
            // Also, as we just want to check sizedness, instead of introducing
            // placeholder lifetimes with probing, we just replace higher lifetimes
            // with fresh vars.
            let output = self.instantiate_binder_with_fresh_vars(
                expr.span,
                infer::BoundRegionConversionTime::FnCall,
                fn_sig.output(),
            );
            self.require_type_is_sized_deferred(
                output,
                call.map_or(expr.span, |e| e.span),
                ObligationCauseCode::SizedCallReturnType,
            );
        }

        // We always require that the type provided as the value for
        // a type parameter outlives the moment of instantiation.
        let args = self.typeck_results.borrow().node_args(expr.hir_id);
        self.add_wf_bounds(args, expr);

        ty
    }

    fn check_expr_break(
        &self,
        destination: hir::Destination,
        expr_opt: Option<&'tcx hir::Expr<'tcx>>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let tcx = self.tcx;
        if let Ok(target_id) = destination.target_id {
            let (e_ty, cause);
            if let Some(e) = expr_opt {
                // If this is a break with a value, we need to type-check
                // the expression. Get an expected type from the loop context.
                let opt_coerce_to = {
                    // We should release `enclosing_breakables` before the `check_expr_with_hint`
                    // below, so can't move this block of code to the enclosing scope and share
                    // `ctxt` with the second `enclosing_breakables` borrow below.
                    let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
                    match enclosing_breakables.opt_find_breakable(target_id) {
                        Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()),
                        None => {
                            // Avoid ICE when `break` is inside a closure (#65383).
                            return Ty::new_error_with_message(
                                tcx,
                                expr.span,
                                "break was outside loop, but no error was emitted",
                            );
                        }
                    }
                };

                // If the loop context is not a `loop { }`, then break with
                // a value is illegal, and `opt_coerce_to` will be `None`.
                // Set expectation to error in that case and set tainted
                // by error (#114529)
                let coerce_to = opt_coerce_to.unwrap_or_else(|| {
                    let guar = tcx.dcx().span_delayed_bug(
                        expr.span,
                        "illegal break with value found but no error reported",
                    );
                    self.set_tainted_by_errors(guar);
                    Ty::new_error(tcx, guar)
                });

                // Recurse without `enclosing_breakables` borrowed.
                e_ty = self.check_expr_with_hint(e, coerce_to);
                cause = self.misc(e.span);
            } else {
                // Otherwise, this is a break *without* a value. That's
                // always legal, and is equivalent to `break ()`.
                e_ty = tcx.types.unit;
                cause = self.misc(expr.span);
            }

            // Now that we have type-checked `expr_opt`, borrow
            // the `enclosing_loops` field and let's coerce the
            // type of `expr_opt` into what is expected.
            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
            let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else {
                // Avoid ICE when `break` is inside a closure (#65383).
                return Ty::new_error_with_message(
                    tcx,
                    expr.span,
                    "break was outside loop, but no error was emitted",
                );
            };

            if let Some(ref mut coerce) = ctxt.coerce {
                if let Some(e) = expr_opt {
                    coerce.coerce(self, &cause, e, e_ty);
                } else {
                    assert!(e_ty.is_unit());
                    let ty = coerce.expected_ty();
                    coerce.coerce_forced_unit(
                        self,
                        &cause,
                        |mut err| {
                            self.suggest_missing_semicolon(&mut err, expr, e_ty, false);
                            self.suggest_mismatched_types_on_tail(
                                &mut err, expr, ty, e_ty, target_id,
                            );
                            let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
                            self.annotate_loop_expected_due_to_inference(err, expr, error);
                            if let Some(val) =
                                self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
                            {
                                err.span_suggestion_verbose(
                                    expr.span.shrink_to_hi(),
                                    "give the `break` a value of the expected type",
                                    format!(" {val}"),
                                    Applicability::HasPlaceholders,
                                );
                            }
                        },
                        false,
                    );
                }
            } else {
                // If `ctxt.coerce` is `None`, we can just ignore
                // the type of the expression. This is because
                // either this was a break *without* a value, in
                // which case it is always a legal type (`()`), or
                // else an error would have been flagged by the
                // `loops` pass for using break with an expression
                // where you are not supposed to.
                assert!(expr_opt.is_none() || self.dcx().has_errors().is_some());
            }

            // If we encountered a `break`, then (no surprise) it may be possible to break from the
            // loop... unless the value being returned from the loop diverges itself, e.g.
            // `break return 5` or `break loop {}`.
            ctxt.may_break |= !self.diverges.get().is_always();

            // the type of a `break` is always `!`, since it diverges
            tcx.types.never
        } else {
            // Otherwise, we failed to find the enclosing loop;
            // this can only happen if the `break` was not
            // inside a loop at all, which is caught by the
            // loop-checking pass.
            let err = Ty::new_error_with_message(
                self.tcx,
                expr.span,
                "break was outside loop, but no error was emitted",
            );

            // We still need to assign a type to the inner expression to
            // prevent the ICE in #43162.
            if let Some(e) = expr_opt {
                self.check_expr_with_hint(e, err);

                // ... except when we try to 'break rust;'.
                // ICE this expression in particular (see #43162).
                if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
                    if let [segment] = path.segments
                        && segment.ident.name == sym::rust
                    {
                        fatally_break_rust(self.tcx, expr.span);
                    }
                }
            }

            // There was an error; make type-check fail.
            err
        }
    }

    fn check_expr_return(
        &self,
        expr_opt: Option<&'tcx hir::Expr<'tcx>>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        if self.ret_coercion.is_none() {
            self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Return);

            if let Some(e) = expr_opt {
                // We still have to type-check `e` (issue #86188), but calling
                // `check_return_expr` only works inside fn bodies.
                self.check_expr(e);
            }
        } else if let Some(e) = expr_opt {
            if self.ret_coercion_span.get().is_none() {
                self.ret_coercion_span.set(Some(e.span));
            }
            self.check_return_expr(e, true);
        } else {
            let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
            if self.ret_coercion_span.get().is_none() {
                self.ret_coercion_span.set(Some(expr.span));
            }
            let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
            if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) {
                coercion.coerce_forced_unit(
                    self,
                    &cause,
                    |db| {
                        let span = fn_decl.output.span();
                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                            db.span_label(
                                span,
                                format!("expected `{snippet}` because of this return type"),
                            );
                        }
                    },
                    true,
                );
            } else {
                coercion.coerce_forced_unit(self, &cause, |_| (), true);
            }
        }
        self.tcx.types.never
    }

    fn check_expr_become(
        &self,
        call: &'tcx hir::Expr<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        match &self.ret_coercion {
            Some(ret_coercion) => {
                let ret_ty = ret_coercion.borrow().expected_ty();
                let call_expr_ty = self.check_expr_with_hint(call, ret_ty);

                // N.B. don't coerce here, as tail calls can't support most/all coercions
                // FIXME(explicit_tail_calls): add a diagnostic note that `become` doesn't allow coercions
                self.demand_suptype(expr.span, ret_ty, call_expr_ty);
            }
            None => {
                self.emit_return_outside_of_fn_body(expr, ReturnLikeStatementKind::Become);

                // Fallback to simply type checking `call` without hint/demanding the right types.
                // Best effort to highlight more errors.
                self.check_expr(call);
            }
        }

        self.tcx.types.never
    }

    /// Check an expression that _is being returned_.
    /// For example, this is called with `return_expr: $expr` when `return $expr`
    /// is encountered.
    ///
    /// Note that this function must only be called in function bodies.
    ///
    /// `explicit_return` is `true` if we're checking an explicit `return expr`,
    /// and `false` if we're checking a trailing expression.
    pub(super) fn check_return_expr(
        &self,
        return_expr: &'tcx hir::Expr<'tcx>,
        explicit_return: bool,
    ) {
        let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
            span_bug!(return_expr.span, "check_return_expr called outside fn body")
        });

        let ret_ty = ret_coercion.borrow().expected_ty();
        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
        let mut span = return_expr.span;
        // Use the span of the trailing expression for our cause,
        // not the span of the entire function
        if !explicit_return
            && let ExprKind::Block(body, _) = return_expr.kind
            && let Some(last_expr) = body.expr
        {
            span = last_expr.span;
        }
        ret_coercion.borrow_mut().coerce(
            self,
            &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
            return_expr,
            return_expr_ty,
        );

        if let Some(fn_sig) = self.body_fn_sig()
            && fn_sig.output().has_opaque_types()
        {
            // Point any obligations that were registered due to opaque type
            // inference at the return expression.
            self.select_obligations_where_possible(|errors| {
                self.point_at_return_for_opaque_ty_error(
                    errors,
                    span,
                    return_expr_ty,
                    return_expr.span,
                );
            });
        }
    }

    /// Emit an error because `return` or `become` is used outside of a function body.
    ///
    /// `expr` is the `return` (`become`) "statement", `kind` is the kind of the statement
    /// either `Return` or `Become`.
    fn emit_return_outside_of_fn_body(&self, expr: &hir::Expr<'_>, kind: ReturnLikeStatementKind) {
        let mut err = ReturnStmtOutsideOfFnBody {
            span: expr.span,
            encl_body_span: None,
            encl_fn_span: None,
            statement_kind: kind,
        };

        let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id);

        if let hir::Node::Item(hir::Item {
            kind: hir::ItemKind::Fn(..), span: encl_fn_span, ..
        })
        | hir::Node::TraitItem(hir::TraitItem {
            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
            span: encl_fn_span,
            ..
        })
        | hir::Node::ImplItem(hir::ImplItem {
            kind: hir::ImplItemKind::Fn(..),
            span: encl_fn_span,
            ..
        }) = self.tcx.hir_node_by_def_id(encl_item_id.def_id)
        {
            // We are inside a function body, so reporting "return statement
            // outside of function body" needs an explanation.

            let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id);

            // If this didn't hold, we would not have to report an error in
            // the first place.
            assert_ne!(encl_item_id.def_id, encl_body_owner_id);

            let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
            let encl_body = self.tcx.hir().body(encl_body_id);

            err.encl_body_span = Some(encl_body.value.span);
            err.encl_fn_span = Some(*encl_fn_span);
        }

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

    fn point_at_return_for_opaque_ty_error(
        &self,
        errors: &mut Vec<traits::FulfillmentError<'tcx>>,
        span: Span,
        return_expr_ty: Ty<'tcx>,
        return_span: Span,
    ) {
        // Don't point at the whole block if it's empty
        if span == return_span {
            return;
        }
        for err in errors {
            let cause = &mut err.obligation.cause;
            if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() {
                let new_cause = ObligationCause::new(
                    cause.span,
                    cause.body_id,
                    ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))),
                );
                *cause = new_cause;
            }
        }
    }

    pub(crate) fn check_lhs_assignable(
        &self,
        lhs: &'tcx hir::Expr<'tcx>,
        code: ErrCode,
        op_span: Span,
        adjust_err: impl FnOnce(&mut Diag<'_>),
    ) {
        if lhs.is_syntactic_place_expr() {
            return;
        }

        let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
        err.code(code);
        err.span_label(lhs.span, "cannot assign to this expression");

        self.comes_from_while_condition(lhs.hir_id, |expr| {
            err.span_suggestion_verbose(
                expr.span.shrink_to_lo(),
                "you might have meant to use pattern destructuring",
                "let ",
                Applicability::MachineApplicable,
            );
        });
        self.check_for_missing_semi(lhs, &mut err);

        adjust_err(&mut err);

        err.emit();
    }

    /// Check if the expression that could not be assigned to was a typoed expression that
    pub fn check_for_missing_semi(&self, expr: &'tcx hir::Expr<'tcx>, err: &mut Diag<'_>) -> bool {
        if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind
            && let hir::BinOpKind::Mul = binop.node
            && self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span))
            && rhs.is_syntactic_place_expr()
        {
            //      v missing semicolon here
            // foo()
            // *bar = baz;
            // (#80446).
            err.span_suggestion_verbose(
                lhs.span.shrink_to_hi(),
                "you might have meant to write a semicolon here",
                ";",
                Applicability::MachineApplicable,
            );
            return true;
        }
        false
    }

    // Check if an expression `original_expr_id` comes from the condition of a while loop,
    /// as opposed from the body of a while loop, which we can naively check by iterating
    /// parents until we find a loop...
    pub(super) fn comes_from_while_condition(
        &self,
        original_expr_id: HirId,
        then: impl FnOnce(&hir::Expr<'_>),
    ) {
        let mut parent = self.tcx.parent_hir_id(original_expr_id);
        loop {
            let node = self.tcx.hir_node(parent);
            match node {
                hir::Node::Expr(hir::Expr {
                    kind:
                        hir::ExprKind::Loop(
                            hir::Block {
                                expr:
                                    Some(hir::Expr {
                                        kind:
                                            hir::ExprKind::Match(expr, ..) | hir::ExprKind::If(expr, ..),
                                        ..
                                    }),
                                ..
                            },
                            _,
                            hir::LoopSource::While,
                            _,
                        ),
                    ..
                }) => {
                    // Check if our original expression is a child of the condition of a while loop.
                    // If it is, then we have a situation like `while Some(0) = value.get(0) {`,
                    // where `while let` was more likely intended.
                    if self.tcx.hir().parent_id_iter(original_expr_id).any(|id| id == expr.hir_id) {
                        then(expr);
                    }
                    break;
                }
                hir::Node::Item(_)
                | hir::Node::ImplItem(_)
                | hir::Node::TraitItem(_)
                | hir::Node::Crate(_) => break,
                _ => {
                    parent = self.tcx.parent_hir_id(parent);
                }
            }
        }
    }

    // A generic function for checking the 'then' and 'else' clauses in an 'if'
    // or 'if-else' expression.
    fn check_then_else(
        &self,
        cond_expr: &'tcx hir::Expr<'tcx>,
        then_expr: &'tcx hir::Expr<'tcx>,
        opt_else_expr: Option<&'tcx hir::Expr<'tcx>>,
        sp: Span,
        orig_expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool, |_| {});

        self.warn_if_unreachable(
            cond_expr.hir_id,
            then_expr.span,
            "block in `if` or `while` expression",
        );

        let cond_diverges = self.diverges.get();
        self.diverges.set(Diverges::Maybe);

        let expected = orig_expected.adjust_for_branches(self);
        let then_ty = self.check_expr_with_expectation(then_expr, expected);
        let then_diverges = self.diverges.get();
        self.diverges.set(Diverges::Maybe);

        // We've already taken the expected type's preferences
        // into account when typing the `then` branch. To figure
        // out the initial shot at a LUB, we thus only consider
        // `expected` if it represents a *hard* constraint
        // (`only_has_type`); otherwise, we just go with a
        // fresh type variable.
        let coerce_to_ty = expected.coercion_target_type(self, sp);
        let mut coerce: DynamicCoerceMany<'_> = CoerceMany::new(coerce_to_ty);

        coerce.coerce(self, &self.misc(sp), then_expr, then_ty);

        if let Some(else_expr) = opt_else_expr {
            let else_ty = self.check_expr_with_expectation(else_expr, expected);
            let else_diverges = self.diverges.get();

            let tail_defines_return_position_impl_trait =
                self.return_position_impl_trait_from_match_expectation(orig_expected);
            let if_cause = self.if_cause(
                sp,
                cond_expr.span,
                then_expr,
                else_expr,
                then_ty,
                else_ty,
                tail_defines_return_position_impl_trait,
            );

            coerce.coerce(self, &if_cause, else_expr, else_ty);

            // We won't diverge unless both branches do (or the condition does).
            self.diverges.set(cond_diverges | then_diverges & else_diverges);
        } else {
            self.if_fallback_coercion(sp, cond_expr, then_expr, &mut coerce);

            // If the condition is false we can't diverge.
            self.diverges.set(cond_diverges);
        }

        let result_ty = coerce.complete(self);
        if let Err(guar) = cond_ty.error_reported() {
            Ty::new_error(self.tcx, guar)
        } else {
            result_ty
        }
    }

    /// Type check assignment expression `expr` of form `lhs = rhs`.
    /// The expected type is `()` and is passed to the function for the purposes of diagnostics.
    fn check_expr_assign(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        expected: Expectation<'tcx>,
        lhs: &'tcx hir::Expr<'tcx>,
        rhs: &'tcx hir::Expr<'tcx>,
        span: Span,
    ) -> Ty<'tcx> {
        let expected_ty = expected.coercion_target_type(self, expr.span);
        if expected_ty == self.tcx.types.bool {
            // The expected type is `bool` but this will result in `()` so we can reasonably
            // say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
            // The likely cause of this is `if foo = bar { .. }`.
            let actual_ty = self.tcx.types.unit;
            let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
            let lhs_ty = self.check_expr(lhs);
            let rhs_ty = self.check_expr(rhs);
            let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
                let lhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, lhs.peel_refs());
                let rhs = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rhs.peel_refs());
                self.can_coerce(rhs, lhs)
            };
            let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
                (Applicability::MachineApplicable, true)
            } else if refs_can_coerce(rhs_ty, lhs_ty) {
                // The lhs and rhs are likely missing some references in either side. Subsequent
                // suggestions will show up.
                (Applicability::MaybeIncorrect, true)
            } else if let ExprKind::Binary(
                Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
                _,
                rhs_expr,
            ) = lhs.kind
            {
                // if x == 1 && y == 2 { .. }
                //                 +
                let actual_lhs_ty = self.check_expr(rhs_expr);
                (
                    Applicability::MaybeIncorrect,
                    self.can_coerce(rhs_ty, actual_lhs_ty)
                        || refs_can_coerce(rhs_ty, actual_lhs_ty),
                )
            } else if let ExprKind::Binary(
                Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
                lhs_expr,
                _,
            ) = rhs.kind
            {
                // if x == 1 && y == 2 { .. }
                //       +
                let actual_rhs_ty = self.check_expr(lhs_expr);
                (
                    Applicability::MaybeIncorrect,
                    self.can_coerce(actual_rhs_ty, lhs_ty)
                        || refs_can_coerce(actual_rhs_ty, lhs_ty),
                )
            } else {
                (Applicability::MaybeIncorrect, false)
            };
            if !lhs.is_syntactic_place_expr()
                && lhs.is_approximately_pattern()
                && !matches!(lhs.kind, hir::ExprKind::Lit(_))
            {
                // Do not suggest `if let x = y` as `==` is way more likely to be the intention.
                if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) =
                    self.tcx.parent_hir_node(expr.hir_id)
                {
                    err.span_suggestion_verbose(
                        expr.span.shrink_to_lo(),
                        "you might have meant to use pattern matching",
                        "let ",
                        applicability,
                    );
                };
            }
            if eq {
                err.span_suggestion_verbose(
                    span.shrink_to_hi(),
                    "you might have meant to compare for equality",
                    '=',
                    applicability,
                );
            }

            // If the assignment expression itself is ill-formed, don't
            // bother emitting another error
            let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
            return Ty::new_error(self.tcx, reported);
        }

        let lhs_ty = self.check_expr_with_needs(lhs, Needs::MutPlace);

        let suggest_deref_binop = |err: &mut Diag<'_>, rhs_ty: Ty<'tcx>| {
            if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
                // Can only assign if the type is sized, so if `DerefMut` yields a type that is
                // unsized, do not suggest dereferencing it.
                let lhs_deref_ty_is_sized = self
                    .infcx
                    .type_implements_trait(
                        self.tcx.require_lang_item(LangItem::Sized, None),
                        [lhs_deref_ty],
                        self.param_env,
                    )
                    .may_apply();
                if lhs_deref_ty_is_sized && self.can_coerce(rhs_ty, lhs_deref_ty) {
                    err.span_suggestion_verbose(
                        lhs.span.shrink_to_lo(),
                        "consider dereferencing here to assign to the mutably borrowed value",
                        "*",
                        Applicability::MachineApplicable,
                    );
                }
            }
        };

        // This is (basically) inlined `check_expr_coercible_to_type`, but we want
        // to suggest an additional fixup here in `suggest_deref_binop`.
        let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
        if let (_, Some(mut diag)) =
            self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
        {
            suggest_deref_binop(&mut diag, rhs_ty);
            diag.emit();
        }

        self.check_lhs_assignable(lhs, E0070, span, |err| {
            if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {
                suggest_deref_binop(err, rhs_ty);
            }
        });

        self.require_type_is_sized(lhs_ty, lhs.span, ObligationCauseCode::AssignmentLhsSized);

        if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {
            Ty::new_error(self.tcx, guar)
        } else {
            self.tcx.types.unit
        }
    }

    pub(super) fn check_expr_let(
        &self,
        let_expr: &'tcx hir::LetExpr<'tcx>,
        hir_id: HirId,
    ) -> Ty<'tcx> {
        // for let statements, this is done in check_stmt
        let init = let_expr.init;
        self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression");
        // otherwise check exactly as a let statement
        self.check_decl((let_expr, hir_id).into());
        // but return a bool, for this is a boolean expression
        if let ast::Recovered::Yes(error_guaranteed) = let_expr.recovered {
            self.set_tainted_by_errors(error_guaranteed);
            Ty::new_error(self.tcx, error_guaranteed)
        } else {
            self.tcx.types.bool
        }
    }

    fn check_expr_loop(
        &self,
        body: &'tcx hir::Block<'tcx>,
        source: hir::LoopSource,
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let coerce = match source {
            // you can only use break with a value from a normal `loop { }`
            hir::LoopSource::Loop => {
                let coerce_to = expected.coercion_target_type(self, body.span);
                Some(CoerceMany::new(coerce_to))
            }

            hir::LoopSource::While | hir::LoopSource::ForLoop => None,
        };

        let ctxt = BreakableCtxt {
            coerce,
            may_break: false, // Will get updated if/when we find a `break`.
        };

        let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || {
            self.check_block_no_value(body);
        });

        if ctxt.may_break {
            // No way to know whether it's diverging because
            // of a `break` or an outer `break` or `return`.
            self.diverges.set(Diverges::Maybe);
        }

        // If we permit break with a value, then result type is
        // the LUB of the breaks (possibly ! if none); else, it
        // is nil. This makes sense because infinite loops
        // (which would have type !) are only possible iff we
        // permit break with a value.
        if ctxt.coerce.is_none() && !ctxt.may_break {
            self.dcx().span_bug(body.span, "no coercion, but loop may not break");
        }
        ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| self.tcx.types.unit)
    }

    /// Checks a method call.
    fn check_method_call(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        segment: &'tcx hir::PathSegment<'tcx>,
        rcvr: &'tcx hir::Expr<'tcx>,
        args: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        let rcvr_t = self.check_expr(rcvr);
        // no need to check for bot/err -- callee does that
        let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
        let span = segment.ident.span;

        let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
            Ok(method) => {
                // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
                // trigger this codepath causing `structurally_resolve_type` to emit an error.
                self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
                Ok(method)
            }
            Err(error) => {
                if segment.ident.name != kw::Empty {
                    if let Some(err) = self.report_method_error(
                        span,
                        rcvr_t,
                        segment.ident,
                        SelfSource::MethodCall(rcvr),
                        error,
                        Some(args),
                        expected,
                        false,
                    ) {
                        err.emit();
                    }
                }
                Err(())
            }
        };

        // Call the generic checker.
        self.check_method_argument_types(span, expr, method, args, DontTupleArguments, expected)
    }

    fn check_expr_cast(
        &self,
        e: &'tcx hir::Expr<'tcx>,
        t: &'tcx hir::Ty<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        // Find the type of `e`. Supply hints based on the type we are casting to,
        // if appropriate.
        let t_cast = self.lower_ty_saving_user_provided_ty(t);
        let t_cast = self.resolve_vars_if_possible(t_cast);
        let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
        let t_expr = self.resolve_vars_if_possible(t_expr);

        // Eagerly check for some obvious errors.
        if let Err(guar) = (t_expr, t_cast).error_reported() {
            Ty::new_error(self.tcx, guar)
        } else {
            // Defer other checks until we're done type checking.
            let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
            match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
                Ok(cast_check) => {
                    debug!(
                        "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
                        t_cast, t_expr, cast_check,
                    );
                    deferred_cast_checks.push(cast_check);
                    t_cast
                }
                Err(guar) => Ty::new_error(self.tcx, guar),
            }
        }
    }

    fn check_expr_array(
        &self,
        args: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let element_ty = if !args.is_empty() {
            let coerce_to = expected
                .to_option(self)
                .and_then(|uty| match *uty.kind() {
                    ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                    _ => None,
                })
                .unwrap_or_else(|| self.next_ty_var(expr.span));
            let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
            assert_eq!(self.diverges.get(), Diverges::Maybe);
            for e in args {
                let e_ty = self.check_expr_with_hint(e, coerce_to);
                let cause = self.misc(e.span);
                coerce.coerce(self, &cause, e, e_ty);
            }
            coerce.complete(self)
        } else {
            self.next_ty_var(expr.span)
        };
        let array_len = args.len() as u64;
        self.suggest_array_len(expr, array_len);
        Ty::new_array(self.tcx, element_ty, array_len)
    }

    fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) {
        let parent_node = self.tcx.hir().parent_iter(expr.hir_id).find(|(_, node)| {
            !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }))
        });
        let Some((
            _,
            hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. })
            | hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }),
        )) = parent_node
        else {
            return;
        };
        if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
            && let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length
        {
            let span = self.tcx.hir().span(hir_id);
            self.dcx().try_steal_modify_and_emit_err(
                span,
                StashKey::UnderscoreForArrayLengths,
                |err| {
                    err.span_suggestion(
                        span,
                        "consider specifying the array length",
                        array_len,
                        Applicability::MaybeIncorrect,
                    );
                },
            );
        }
    }

    fn check_expr_const_block(
        &self,
        block: &'tcx hir::ConstBlock,
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        let body = self.tcx.hir().body(block.body);

        // Create a new function context.
        let def_id = block.def_id;
        let fcx = FnCtxt::new(self, self.param_env, def_id);
        crate::GatherLocalsVisitor::new(&fcx).visit_body(body);

        let ty = fcx.check_expr_with_expectation(body.value, expected);
        fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized);
        fcx.write_ty(block.hir_id, ty);
        ty
    }

    fn check_expr_repeat(
        &self,
        element: &'tcx hir::Expr<'tcx>,
        count: &'tcx hir::ArrayLen<'tcx>,
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let tcx = self.tcx;
        let count = self.lower_array_length(count);
        if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
            self.suggest_array_len(expr, count);
        }

        let uty = match expected {
            ExpectHasType(uty) => match *uty.kind() {
                ty::Array(ty, _) | ty::Slice(ty) => Some(ty),
                _ => None,
            },
            _ => None,
        };

        let (element_ty, t) = match uty {
            Some(uty) => {
                self.check_expr_coercible_to_type(element, uty, None);
                (uty, uty)
            }
            None => {
                let ty = self.next_ty_var(element.span);
                let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});
                (element_ty, ty)
            }
        };

        if let Err(guar) = element_ty.error_reported() {
            return Ty::new_error(tcx, guar);
        }

        self.check_repeat_element_needs_copy_bound(element, count, element_ty);

        let ty = Ty::new_array_with_const_len(tcx, t, count);

        self.register_wf_obligation(ty.into(), expr.span, ObligationCauseCode::WellFormed(None));

        ty
    }

    fn check_repeat_element_needs_copy_bound(
        &self,
        element: &hir::Expr<'_>,
        count: ty::Const<'tcx>,
        element_ty: Ty<'tcx>,
    ) {
        let tcx = self.tcx;
        // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
        match &element.kind {
            hir::ExprKind::ConstBlock(..) => return,
            hir::ExprKind::Path(qpath) => {
                let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
                if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res
                {
                    return;
                }
            }
            _ => {}
        }
        // If someone calls a const fn or constructs a const value, they can extract that
        // out into a separate constant (or a const block in the future), so we check that
        // to tell them that in the diagnostic. Does not affect typeck.
        let is_constable = match element.kind {
            hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
                ty::FnDef(def_id, _) if tcx.is_const_fn(def_id) => traits::IsConstable::Fn,
                _ => traits::IsConstable::No,
            },
            hir::ExprKind::Path(qpath) => {
                match self.typeck_results.borrow().qpath_res(&qpath, element.hir_id) {
                    Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => traits::IsConstable::Ctor,
                    _ => traits::IsConstable::No,
                }
            }
            _ => traits::IsConstable::No,
        };

        // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
        // don't copy that one element, we move it. Only check for Copy if the length is larger.
        if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
            let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
            let code = traits::ObligationCauseCode::RepeatElementCopy {
                is_constable,
                elt_type: element_ty,
                elt_span: element.span,
                elt_stmt_span: self
                    .tcx
                    .hir()
                    .parent_iter(element.hir_id)
                    .find_map(|(_, node)| match node {
                        hir::Node::Item(it) => Some(it.span),
                        hir::Node::Stmt(stmt) => Some(stmt.span),
                        _ => None,
                    })
                    .expect("array repeat expressions must be inside an item or statement"),
            };
            self.require_type_meets(element_ty, element.span, code, lang_item);
        }
    }

    fn check_expr_tuple(
        &self,
        elts: &'tcx [hir::Expr<'tcx>],
        expected: Expectation<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let flds = expected.only_has_type(self).and_then(|ty| {
            let ty = self.resolve_vars_with_obligations(ty);
            match ty.kind() {
                ty::Tuple(flds) => Some(&flds[..]),
                _ => None,
            }
        });

        let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
            Some(fs) if i < fs.len() => {
                let ety = fs[i];
                self.check_expr_coercible_to_type(e, ety, None);
                ety
            }
            _ => self.check_expr_with_expectation(e, NoExpectation),
        });
        let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter);
        if let Err(guar) = tuple.error_reported() {
            Ty::new_error(self.tcx, guar)
        } else {
            self.require_type_is_sized(
                tuple,
                expr.span,
                ObligationCauseCode::TupleInitializerSized,
            );
            tuple
        }
    }

    fn check_expr_struct(
        &self,
        expr: &hir::Expr<'_>,
        expected: Expectation<'tcx>,
        qpath: &QPath<'tcx>,
        fields: &'tcx [hir::ExprField<'tcx>],
        base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
    ) -> Ty<'tcx> {
        // Find the relevant variant
        let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) {
            Ok(data) => data,
            Err(guar) => {
                self.check_struct_fields_on_error(fields, base_expr);
                return Ty::new_error(self.tcx, guar);
            }
        };

        // Prohibit struct expressions when non-exhaustive flag is set.
        let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
        if !adt.did().is_local() && variant.is_field_list_non_exhaustive() {
            self.dcx()
                .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() });
        }

        self.check_expr_struct_fields(
            adt_ty,
            expected,
            expr,
            qpath.span(),
            variant,
            fields,
            base_expr,
        );

        self.require_type_is_sized(adt_ty, expr.span, ObligationCauseCode::StructInitializerSized);
        adt_ty
    }

    fn check_expr_struct_fields(
        &self,
        adt_ty: Ty<'tcx>,
        expected: Expectation<'tcx>,
        expr: &hir::Expr<'_>,
        span: Span,
        variant: &'tcx ty::VariantDef,
        hir_fields: &'tcx [hir::ExprField<'tcx>],
        base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
    ) {
        let tcx = self.tcx;

        let expected_inputs =
            self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]);
        let adt_ty_hint = if let Some(expected_inputs) = expected_inputs {
            expected_inputs.get(0).cloned().unwrap_or(adt_ty)
        } else {
            adt_ty
        };
        // re-link the regions that EIfEO can erase.
        self.demand_eqtype(span, adt_ty_hint, adt_ty);

        let ty::Adt(adt, args) = adt_ty.kind() else {
            span_bug!(span, "non-ADT passed to check_expr_struct_fields");
        };
        let adt_kind = adt.adt_kind();

        let mut remaining_fields = variant
            .fields
            .iter_enumerated()
            .map(|(i, field)| (field.ident(tcx).normalize_to_macros_2_0(), (i, field)))
            .collect::<UnordMap<_, _>>();

        let mut seen_fields = FxHashMap::default();

        let mut error_happened = false;

        // Type-check each field.
        for (idx, field) in hir_fields.iter().enumerate() {
            let ident = tcx.adjust_ident(field.ident, variant.def_id);
            let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
                seen_fields.insert(ident, field.span);
                // FIXME: handle nested fields
                self.write_field_index(field.hir_id, i, Vec::new());

                // We don't look at stability attributes on
                // struct-like enums (yet...), but it's definitely not
                // a bug to have constructed one.
                if adt_kind != AdtKind::Enum {
                    tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None);
                }

                self.field_ty(field.span, v_field, args)
            } else {
                error_happened = true;
                let guar = if let Some(prev_span) = seen_fields.get(&ident) {
                    tcx.dcx().emit_err(FieldMultiplySpecifiedInInitializer {
                        span: field.ident.span,
                        prev_span: *prev_span,
                        ident,
                    })
                } else {
                    self.report_unknown_field(
                        adt_ty,
                        variant,
                        expr,
                        field,
                        hir_fields,
                        adt.variant_descr(),
                    )
                };

                Ty::new_error(tcx, guar)
            };

            // Make sure to give a type to the field even if there's
            // an error, so we can continue type-checking.
            let ty = self.check_expr_with_hint(field.expr, field_type);
            let (_, diag) =
                self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);

            if let Some(diag) = diag {
                if idx == hir_fields.len() - 1 {
                    if remaining_fields.is_empty() {
                        self.suggest_fru_from_range_and_emit(field, variant, args, diag);
                    } else {
                        diag.stash(field.span, StashKey::MaybeFruTypo);
                    }
                } else {
                    diag.emit();
                }
            }
        }

        // Make sure the programmer specified correct number of fields.
        if adt_kind == AdtKind::Union {
            if hir_fields.len() != 1 {
                struct_span_code_err!(
                    tcx.dcx(),
                    span,
                    E0784,
                    "union expressions should have exactly one field",
                )
                .emit();
            }
        }

        // If check_expr_struct_fields hit an error, do not attempt to populate
        // the fields with the base_expr. This could cause us to hit errors later
        // when certain fields are assumed to exist that in fact do not.
        if error_happened {
            if let Some(base_expr) = base_expr {
                self.check_expr(base_expr);
            }
            return;
        }

        if let Some(base_expr) = base_expr {
            // FIXME: We are currently creating two branches here in order to maintain
            // consistency. But they should be merged as much as possible.
            let fru_tys = if self.tcx.features().type_changing_struct_update {
                if adt.is_struct() {
                    // Make some fresh generic parameters for our ADT type.
                    let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
                    // We do subtyping on the FRU fields first, so we can
                    // learn exactly what types we expect the base expr
                    // needs constrained to be compatible with the struct
                    // type we expect from the expectation value.
                    let fru_tys = variant
                        .fields
                        .iter()
                        .map(|f| {
                            let fru_ty = self
                                .normalize(expr.span, self.field_ty(base_expr.span, f, fresh_args));
                            let ident = self.tcx.adjust_ident(f.ident(self.tcx), variant.def_id);
                            if let Some(_) = remaining_fields.remove(&ident) {
                                let target_ty = self.field_ty(base_expr.span, f, args);
                                let cause = self.misc(base_expr.span);
                                match self.at(&cause, self.param_env).sup(
                                    // We're already using inference variables for any params, and don't allow converting
                                    // between different structs, so there is no way this ever actually defines an opaque type.
                                    // Thus choosing `Yes` is fine.
                                    DefineOpaqueTypes::Yes,
                                    target_ty,
                                    fru_ty,
                                ) {
                                    Ok(InferOk { obligations, value: () }) => {
                                        self.register_predicates(obligations)
                                    }
                                    Err(_) => {
                                        span_bug!(
                                            cause.span(),
                                            "subtyping remaining fields of type changing FRU failed: {target_ty} != {fru_ty}: {}::{}",
                                            variant.name,
                                            ident.name,
                                        );
                                    }
                                }
                            }
                            self.resolve_vars_if_possible(fru_ty)
                        })
                        .collect();
                    // The use of fresh args that we have subtyped against
                    // our base ADT type's fields allows us to guide inference
                    // along so that, e.g.
                    // ```
                    // MyStruct<'a, F1, F2, const C: usize> {
                    //     f: F1,
                    //     // Other fields that reference `'a`, `F2`, and `C`
                    // }
                    //
                    // let x = MyStruct {
                    //    f: 1usize,
                    //    ..other_struct
                    // };
                    // ```
                    // will have the `other_struct` expression constrained to
                    // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
                    // This is important to allow coercions to happen in
                    // `other_struct` itself. See `coerce-in-base-expr.rs`.
                    let fresh_base_ty = Ty::new_adt(self.tcx, *adt, fresh_args);
                    self.check_expr_has_type_or_error(
                        base_expr,
                        self.resolve_vars_if_possible(fresh_base_ty),
                        |_| {},
                    );
                    fru_tys
                } else {
                    // Check the base_expr, regardless of a bad expected adt_ty, so we can get
                    // type errors on that expression, too.
                    self.check_expr(base_expr);
                    self.dcx().emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
                    return;
                }
            } else {
                self.check_expr_has_type_or_error(base_expr, adt_ty, |_| {
                    let base_ty = self.typeck_results.borrow().expr_ty(*base_expr);
                    let same_adt = matches!((adt_ty.kind(), base_ty.kind()),
                        (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt);
                    if self.tcx.sess.is_nightly_build() && same_adt {
                        feature_err(
                            &self.tcx.sess,
                            sym::type_changing_struct_update,
                            base_expr.span,
                            "type changing struct updating is experimental",
                        )
                        .emit();
                    }
                });
                match adt_ty.kind() {
                    ty::Adt(adt, args) if adt.is_struct() => variant
                        .fields
                        .iter()
                        .map(|f| self.normalize(expr.span, f.ty(self.tcx, args)))
                        .collect(),
                    _ => {
                        self.dcx()
                            .emit_err(FunctionalRecordUpdateOnNonStruct { span: base_expr.span });
                        return;
                    }
                }
            };
            self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr.hir_id, fru_tys);
        } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() {
            debug!(?remaining_fields);
            let private_fields: Vec<&ty::FieldDef> = variant
                .fields
                .iter()
                .filter(|field| !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx))
                .collect();

            if !private_fields.is_empty() {
                self.report_private_fields(adt_ty, span, expr.span, private_fields, hir_fields);
            } else {
                self.report_missing_fields(
                    adt_ty,
                    span,
                    remaining_fields,
                    variant,
                    hir_fields,
                    args,
                );
            }
        }
    }

    fn check_struct_fields_on_error(
        &self,
        fields: &'tcx [hir::ExprField<'tcx>],
        base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
    ) {
        for field in fields {
            self.check_expr(field.expr);
        }
        if let Some(base) = *base_expr {
            self.check_expr(base);
        }
    }

    /// Report an error for a struct field expression when there are fields which aren't provided.
    ///
    /// ```text
    /// error: missing field `you_can_use_this_field` in initializer of `foo::Foo`
    ///  --> src/main.rs:8:5
    ///   |
    /// 8 |     foo::Foo {};
    ///   |     ^^^^^^^^ missing `you_can_use_this_field`
    ///
    /// error: aborting due to 1 previous error
    /// ```
    fn report_missing_fields(
        &self,
        adt_ty: Ty<'tcx>,
        span: Span,
        remaining_fields: UnordMap<Ident, (FieldIdx, &ty::FieldDef)>,
        variant: &'tcx ty::VariantDef,
        hir_fields: &'tcx [hir::ExprField<'tcx>],
        args: GenericArgsRef<'tcx>,
    ) {
        let len = remaining_fields.len();

        let displayable_field_names: Vec<&str> =
            remaining_fields.items().map(|(ident, _)| ident.as_str()).into_sorted_stable_ord();

        let mut truncated_fields_error = String::new();
        let remaining_fields_names = match &displayable_field_names[..] {
            [field1] => format!("`{field1}`"),
            [field1, field2] => format!("`{field1}` and `{field2}`"),
            [field1, field2, field3] => format!("`{field1}`, `{field2}` and `{field3}`"),
            _ => {
                truncated_fields_error =
                    format!(" and {} other field{}", len - 3, pluralize!(len - 3));
                displayable_field_names
                    .iter()
                    .take(3)
                    .map(|n| format!("`{n}`"))
                    .collect::<Vec<_>>()
                    .join(", ")
            }
        };

        let mut err = struct_span_code_err!(
            self.dcx(),
            span,
            E0063,
            "missing field{} {}{} in initializer of `{}`",
            pluralize!(len),
            remaining_fields_names,
            truncated_fields_error,
            adt_ty
        );
        err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));

        if let Some(hir_field) = hir_fields.last() {
            self.suggest_fru_from_range_and_emit(hir_field, variant, args, err);
        } else {
            err.emit();
        }
    }

    /// If the last field is a range literal, but it isn't supposed to be, then they probably
    /// meant to use functional update syntax.
    fn suggest_fru_from_range_and_emit(
        &self,
        last_expr_field: &hir::ExprField<'tcx>,
        variant: &ty::VariantDef,
        args: GenericArgsRef<'tcx>,
        mut err: Diag<'_>,
    ) {
        // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
        if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [range_start, range_end], _) =
            last_expr_field.expr.kind
            && let variant_field =
                variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident)
            && let range_def_id = self.tcx.lang_items().range_struct()
            && variant_field
                .and_then(|field| field.ty(self.tcx, args).ty_adt_def())
                .map(|adt| adt.did())
                != range_def_id
        {
            // Use a (somewhat arbitrary) filtering heuristic to avoid printing
            // expressions that are either too long, or have control character
            // such as newlines in them.
            let expr = self
                .tcx
                .sess
                .source_map()
                .span_to_snippet(range_end.expr.span)
                .ok()
                .filter(|s| s.len() < 25 && !s.contains(|c: char| c.is_control()));

            let fru_span = self
                .tcx
                .sess
                .source_map()
                .span_extend_while_whitespace(range_start.span)
                .shrink_to_hi()
                .to(range_end.span);

            err.subdiagnostic(
                self.dcx(),
                TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr },
            );

            // Suppress any range expr type mismatches
            self.dcx().try_steal_replace_and_emit_err(
                last_expr_field.span,
                StashKey::MaybeFruTypo,
                err,
            );
        } else {
            err.emit();
        }
    }

    /// Report an error for a struct field expression when there are invisible fields.
    ///
    /// ```text
    /// error: cannot construct `Foo` with struct literal syntax due to private fields
    ///  --> src/main.rs:8:5
    ///   |
    /// 8 |     foo::Foo {};
    ///   |     ^^^^^^^^
    ///
    /// error: aborting due to 1 previous error
    /// ```
    fn report_private_fields(
        &self,
        adt_ty: Ty<'tcx>,
        span: Span,
        expr_span: Span,
        private_fields: Vec<&ty::FieldDef>,
        used_fields: &'tcx [hir::ExprField<'tcx>],
    ) {
        let mut err =
            self.dcx().struct_span_err(
                span,
                format!(
                    "cannot construct `{adt_ty}` with struct literal syntax due to private fields",
                ),
            );
        let (used_private_fields, remaining_private_fields): (
            Vec<(Symbol, Span, bool)>,
            Vec<(Symbol, Span, bool)>,
        ) = private_fields
            .iter()
            .map(|field| {
                match used_fields.iter().find(|used_field| field.name == used_field.ident.name) {
                    Some(used_field) => (field.name, used_field.span, true),
                    None => (field.name, self.tcx.def_span(field.did), false),
                }
            })
            .partition(|field| field.2);
        err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field");
        if !remaining_private_fields.is_empty() {
            let remaining_private_fields_len = remaining_private_fields.len();
            let names = match &remaining_private_fields
                .iter()
                .map(|(name, _, _)| name)
                .collect::<Vec<_>>()[..]
            {
                _ if remaining_private_fields_len > 6 => String::new(),
                [name] => format!("`{name}` "),
                [names @ .., last] => {
                    let names = names.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
                    format!("{} and `{last}` ", names.join(", "))
                }
                [] => bug!("expected at least one private field to report"),
            };
            err.note(format!(
                "{}private field{s} {names}that {were} not provided",
                if used_fields.is_empty() { "" } else { "...and other " },
                s = pluralize!(remaining_private_fields_len),
                were = pluralize!("was", remaining_private_fields_len),
            ));
        }

        if let ty::Adt(def, _) = adt_ty.kind() {
            let def_id = def.did();
            let mut items = self
                .tcx
                .inherent_impls(def_id)
                .into_iter()
                .flatten()
                .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
                // Only assoc fn with no receivers.
                .filter(|item| {
                    matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter
                })
                .filter_map(|item| {
                    // Only assoc fns that return `Self`
                    let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
                    let ret_ty = fn_sig.output();
                    let ret_ty =
                        self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty);
                    if !self.can_eq(self.param_env, ret_ty, adt_ty) {
                        return None;
                    }
                    let input_len = fn_sig.inputs().skip_binder().len();
                    let order = !item.name.as_str().starts_with("new");
                    Some((order, item.name, input_len))
                })
                .collect::<Vec<_>>();
            items.sort_by_key(|(order, _, _)| *order);
            let suggestion = |name, args| {
                format!(
                    "::{name}({})",
                    std::iter::repeat("_").take(args).collect::<Vec<_>>().join(", ")
                )
            };
            match &items[..] {
                [] => {}
                [(_, name, args)] => {
                    err.span_suggestion_verbose(
                        span.shrink_to_hi().with_hi(expr_span.hi()),
                        format!("you might have meant to use the `{name}` associated function"),
                        suggestion(name, *args),
                        Applicability::MaybeIncorrect,
                    );
                }
                _ => {
                    err.span_suggestions(
                        span.shrink_to_hi().with_hi(expr_span.hi()),
                        "you might have meant to use an associated function to build this type",
                        items.iter().map(|(_, name, args)| suggestion(name, *args)),
                        Applicability::MaybeIncorrect,
                    );
                }
            }
            if let Some(default_trait) = self.tcx.get_diagnostic_item(sym::Default)
                && self
                    .infcx
                    .type_implements_trait(default_trait, [adt_ty], self.param_env)
                    .may_apply()
            {
                err.multipart_suggestion(
                    "consider using the `Default` trait",
                    vec![
                        (span.shrink_to_lo(), "<".to_string()),
                        (
                            span.shrink_to_hi().with_hi(expr_span.hi()),
                            " as std::default::Default>::default()".to_string(),
                        ),
                    ],
                    Applicability::MaybeIncorrect,
                );
            }
        }

        err.emit();
    }

    fn report_unknown_field(
        &self,
        ty: Ty<'tcx>,
        variant: &'tcx ty::VariantDef,
        expr: &hir::Expr<'_>,
        field: &hir::ExprField<'_>,
        skip_fields: &[hir::ExprField<'_>],
        kind_name: &str,
    ) -> ErrorGuaranteed {
        if variant.is_recovered() {
            let guar =
                self.dcx().span_delayed_bug(expr.span, "parser recovered but no error was emitted");
            self.set_tainted_by_errors(guar);
            return guar;
        }
        let mut err = self.err_ctxt().type_error_struct_with_diag(
            field.ident.span,
            |actual| match ty.kind() {
                ty::Adt(adt, ..) if adt.is_enum() => struct_span_code_err!(
                    self.dcx(),
                    field.ident.span,
                    E0559,
                    "{} `{}::{}` has no field named `{}`",
                    kind_name,
                    actual,
                    variant.name,
                    field.ident
                ),
                _ => struct_span_code_err!(
                    self.dcx(),
                    field.ident.span,
                    E0560,
                    "{} `{}` has no field named `{}`",
                    kind_name,
                    actual,
                    field.ident
                ),
            },
            ty,
        );

        let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
        match variant.ctor_kind() {
            Some(CtorKind::Fn) => match ty.kind() {
                ty::Adt(adt, ..) if adt.is_enum() => {
                    err.span_label(
                        variant_ident_span,
                        format!(
                            "`{adt}::{variant}` defined here",
                            adt = ty,
                            variant = variant.name,
                        ),
                    );
                    err.span_label(field.ident.span, "field does not exist");
                    err.span_suggestion_verbose(
                        expr.span,
                        format!(
                            "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
                            adt = ty,
                            variant = variant.name,
                        ),
                        format!(
                            "{adt}::{variant}(/* fields */)",
                            adt = ty,
                            variant = variant.name,
                        ),
                        Applicability::HasPlaceholders,
                    );
                }
                _ => {
                    err.span_label(variant_ident_span, format!("`{ty}` defined here"));
                    err.span_label(field.ident.span, "field does not exist");
                    err.span_suggestion_verbose(
                        expr.span,
                        format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
                        format!("{ty}(/* fields */)"),
                        Applicability::HasPlaceholders,
                    );
                }
            },
            _ => {
                // prevent all specified fields from being suggested
                let available_field_names = self.available_field_names(variant, expr, skip_fields);
                if let Some(field_name) =
                    find_best_match_for_name(&available_field_names, field.ident.name, None)
                {
                    err.span_label(field.ident.span, "unknown field");
                    err.span_suggestion_verbose(
                        field.ident.span,
                        "a field with a similar name exists",
                        field_name,
                        Applicability::MaybeIncorrect,
                    );
                } else {
                    match ty.kind() {
                        ty::Adt(adt, ..) => {
                            if adt.is_enum() {
                                err.span_label(
                                    field.ident.span,
                                    format!("`{}::{}` does not have this field", ty, variant.name),
                                );
                            } else {
                                err.span_label(
                                    field.ident.span,
                                    format!("`{ty}` does not have this field"),
                                );
                            }
                            if available_field_names.is_empty() {
                                err.note("all struct fields are already assigned");
                            } else {
                                err.note(format!(
                                    "available fields are: {}",
                                    self.name_series_display(available_field_names)
                                ));
                            }
                        }
                        _ => bug!("non-ADT passed to report_unknown_field"),
                    }
                };
            }
        }
        err.emit()
    }

    fn available_field_names(
        &self,
        variant: &'tcx ty::VariantDef,
        expr: &hir::Expr<'_>,
        skip_fields: &[hir::ExprField<'_>],
    ) -> Vec<Symbol> {
        variant
            .fields
            .iter()
            .filter(|field| {
                skip_fields.iter().all(|&skip| skip.ident.name != field.name)
                    && self.is_field_suggestable(field, expr.hir_id, expr.span)
            })
            .map(|field| field.name)
            .collect()
    }

    fn name_series_display(&self, names: Vec<Symbol>) -> String {
        // dynamic limit, to never omit just one field
        let limit = if names.len() == 6 { 6 } else { 5 };
        let mut display =
            names.iter().take(limit).map(|n| format!("`{n}`")).collect::<Vec<_>>().join(", ");
        if names.len() > limit {
            display = format!("{} ... and {} others", display, names.len() - limit);
        }
        display
    }

    // Check field access expressions
    fn check_field(
        &self,
        expr: &'tcx hir::Expr<'tcx>,
        base: &'tcx hir::Expr<'tcx>,
        field: Ident,
        expected: Expectation<'tcx>,
    ) -> Ty<'tcx> {
        debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field);
        let base_ty = self.check_expr(base);
        let base_ty = self.structurally_resolve_type(base.span, base_ty);
        let mut private_candidate = None;
        let mut autoderef = self.autoderef(expr.span, base_ty);
        while let Some((deref_base_ty, _)) = autoderef.next() {
            debug!("deref_base_ty: {:?}", deref_base_ty);
            match deref_base_ty.kind() {
                ty::Adt(base_def, args) if !base_def.is_enum() => {
                    debug!("struct named {:?}", deref_base_ty);
                    let body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
                    let (ident, def_scope) =
                        self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
                    let mut adt_def = *base_def;
                    let mut last_ty = None;
                    let mut nested_fields = Vec::new();
                    let mut index = None;
                    while let Some(idx) = self.tcx.find_field((adt_def.did(), ident)) {
                        let &mut first_idx = index.get_or_insert(idx);
                        let field = &adt_def.non_enum_variant().fields[idx];
                        let field_ty = self.field_ty(expr.span, field, args);
                        if let Some(ty) = last_ty {
                            nested_fields.push((ty, idx));
                        }
                        if field.ident(self.tcx).normalize_to_macros_2_0() == ident {
                            // Save the index of all fields regardless of their visibility in case
                            // of error recovery.
                            self.write_field_index(expr.hir_id, first_idx, nested_fields);
                            let adjustments = self.adjust_steps(&autoderef);
                            if field.vis.is_accessible_from(def_scope, self.tcx) {
                                self.apply_adjustments(base, adjustments);
                                self.register_predicates(autoderef.into_obligations());

                                self.tcx.check_stability(
                                    field.did,
                                    Some(expr.hir_id),
                                    expr.span,
                                    None,
                                );
                                return field_ty;
                            }
                            private_candidate = Some((adjustments, base_def.did()));
                            break;
                        }
                        last_ty = Some(field_ty);
                        adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field");
                    }
                }
                ty::Tuple(tys) => {
                    if let Ok(index) = field.as_str().parse::<usize>() {
                        if field.name == sym::integer(index) {
                            if let Some(&field_ty) = tys.get(index) {
                                let adjustments = self.adjust_steps(&autoderef);
                                self.apply_adjustments(base, adjustments);
                                self.register_predicates(autoderef.into_obligations());

                                self.write_field_index(
                                    expr.hir_id,
                                    FieldIdx::from_usize(index),
                                    Vec::new(),
                                );
                                return field_ty;
                            }
                        }
                    }
                }
                _ => {}
            }
        }
        self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));

        if let Some((adjustments, did)) = private_candidate {
            // (#90483) apply adjustments to avoid ExprUseVisitor from
            // creating erroneous projection.
            self.apply_adjustments(base, adjustments);
            let guar = self.ban_private_field_access(
                expr,
                base_ty,
                field,
                did,
                expected.only_has_type(self),
            );
            return Ty::new_error(self.tcx(), guar);
        }

        let guar = if field.name == kw::Empty {
            self.dcx().span_delayed_bug(field.span, "field name with no name")
        } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
            self.ban_take_value_of_method(expr, base_ty, field)
        } else if !base_ty.is_primitive_ty() {
            self.ban_nonexisting_field(field, base, expr, base_ty)
        } else {
            let field_name = field.to_string();
            let mut err = type_error_struct!(
                self.dcx(),
                field.span,
                base_ty,
                E0610,
                "`{base_ty}` is a primitive type and therefore doesn't have fields",
            );
            let is_valid_suffix = |field: &str| {
                if field == "f32" || field == "f64" {
                    return true;
                }
                let mut chars = field.chars().peekable();
                match chars.peek() {
                    Some('e') | Some('E') => {
                        chars.next();
                        if let Some(c) = chars.peek()
                            && !c.is_numeric()
                            && *c != '-'
                            && *c != '+'
                        {
                            return false;
                        }
                        while let Some(c) = chars.peek() {
                            if !c.is_numeric() {
                                break;
                            }
                            chars.next();
                        }
                    }
                    _ => (),
                }
                let suffix = chars.collect::<String>();
                suffix.is_empty() || suffix == "f32" || suffix == "f64"
            };
            let maybe_partial_suffix = |field: &str| -> Option<&str> {
                let first_chars = ['f', 'l'];
                if field.len() >= 1
                    && field.to_lowercase().starts_with(first_chars)
                    && field[1..].chars().all(|c| c.is_ascii_digit())
                {
                    if field.to_lowercase().starts_with(['f']) { Some("f32") } else { Some("f64") }
                } else {
                    None
                }
            };
            if let ty::Infer(ty::IntVar(_)) = base_ty.kind()
                && let ExprKind::Lit(Spanned {
                    node: ast::LitKind::Int(_, ast::LitIntType::Unsuffixed),
                    ..
                }) = base.kind
                && !base.span.from_expansion()
            {
                if is_valid_suffix(&field_name) {
                    err.span_suggestion_verbose(
                        field.span.shrink_to_lo(),
                        "if intended to be a floating point literal, consider adding a `0` after the period",
                        '0',
                        Applicability::MaybeIncorrect,
                    );
                } else if let Some(correct_suffix) = maybe_partial_suffix(&field_name) {
                    err.span_suggestion_verbose(
                        field.span,
                        format!("if intended to be a floating point literal, consider adding a `0` after the period and a `{correct_suffix}` suffix"),
                        format!("0{correct_suffix}"),
                        Applicability::MaybeIncorrect,
                    );
                }
            }
            err.emit()
        };

        Ty::new_error(self.tcx(), guar)
    }

    fn suggest_await_on_field_access(
        &self,
        err: &mut Diag<'_>,
        field_ident: Ident,
        base: &'tcx hir::Expr<'tcx>,
        ty: Ty<'tcx>,
    ) {
        let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
            err.span_label(field_ident.span, "unknown field");
            return;
        };
        let ty::Adt(def, _) = output_ty.kind() else {
            err.span_label(field_ident.span, "unknown field");
            return;
        };
        // no field access on enum type
        if def.is_enum() {
            err.span_label(field_ident.span, "unknown field");
            return;
        }
        if !def.non_enum_variant().fields.iter().any(|field| field.ident(self.tcx) == field_ident) {
            err.span_label(field_ident.span, "unknown field");
            return;
        }
        err.span_label(
            field_ident.span,
            "field not available in `impl Future`, but it is available in its `Output`",
        );
        err.span_suggestion_verbose(
            base.span.shrink_to_hi(),
            "consider `await`ing on the `Future` and access the field of its `Output`",
            ".await",
            Applicability::MaybeIncorrect,
        );
    }

    fn ban_nonexisting_field(
        &self,
        ident: Ident,
        base: &'tcx hir::Expr<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
        base_ty: Ty<'tcx>,
    ) -> ErrorGuaranteed {
        debug!(
            "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}",
            ident, base, expr, base_ty
        );
        let mut err = self.no_such_field_err(ident, base_ty, base.hir_id);

        match *base_ty.peel_refs().kind() {
            ty::Array(_, len) => {
                self.maybe_suggest_array_indexing(&mut err, expr, base, ident, len);
            }
            ty::RawPtr(..) => {
                self.suggest_first_deref_field(&mut err, expr, base, ident);
            }
            ty::Param(param_ty) => {
                err.span_label(ident.span, "unknown field");
                self.point_at_param_definition(&mut err, param_ty);
            }
            ty::Alias(ty::Opaque, _) => {
                self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
            }
            _ => {
                err.span_label(ident.span, "unknown field");
            }
        }

        self.suggest_fn_call(&mut err, base, base_ty, |output_ty| {
            if let ty::Adt(def, _) = output_ty.kind()
                && !def.is_enum()
            {
                def.non_enum_variant().fields.iter().any(|field| {
                    field.ident(self.tcx) == ident
                        && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
                })
            } else if let ty::Tuple(tys) = output_ty.kind()
                && let Ok(idx) = ident.as_str().parse::<usize>()
            {
                idx < tys.len()
            } else {
                false
            }
        });

        if ident.name == kw::Await {
            // We know by construction that `<expr>.await` is either on Rust 2015
            // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
            err.note("to `.await` a `Future`, switch to Rust 2018 or later");
            HelpUseLatestEdition::new().add_to_diag(&mut err);
        }

        err.emit()
    }

    fn ban_private_field_access(
        &self,
        expr: &hir::Expr<'tcx>,
        expr_t: Ty<'tcx>,
        field: Ident,
        base_did: DefId,
        return_ty: Option<Ty<'tcx>>,
    ) -> ErrorGuaranteed {
        let mut err = self.private_field_err(field, base_did);

        // Also check if an accessible method exists, which is often what is meant.
        if self.method_exists(field, expr_t, expr.hir_id, return_ty)
            && !self.expr_in_place(expr.hir_id)
        {
            self.suggest_method_call(
                &mut err,
                format!("a method `{field}` also exists, call it with parentheses"),
                field,
                expr_t,
                expr,
                None,
            );
        }
        err.emit()
    }

    fn ban_take_value_of_method(
        &self,
        expr: &hir::Expr<'tcx>,
        expr_t: Ty<'tcx>,
        field: Ident,
    ) -> ErrorGuaranteed {
        let mut err = type_error_struct!(
            self.dcx(),
            field.span,
            expr_t,
            E0615,
            "attempted to take value of method `{field}` on type `{expr_t}`",
        );
        err.span_label(field.span, "method, not a field");
        let expr_is_call =
            if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
                self.tcx.parent_hir_node(expr.hir_id)
            {
                expr.hir_id == callee.hir_id
            } else {
                false
            };
        let expr_snippet =
            self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or_default();
        let is_wrapped = expr_snippet.starts_with('(') && expr_snippet.ends_with(')');
        let after_open = expr.span.lo() + rustc_span::BytePos(1);
        let before_close = expr.span.hi() - rustc_span::BytePos(1);

        if expr_is_call && is_wrapped {
            err.multipart_suggestion(
                "remove wrapping parentheses to call the method",
                vec![
                    (expr.span.with_hi(after_open), String::new()),
                    (expr.span.with_lo(before_close), String::new()),
                ],
                Applicability::MachineApplicable,
            );
        } else if !self.expr_in_place(expr.hir_id) {
            // Suggest call parentheses inside the wrapping parentheses
            let span = if is_wrapped {
                expr.span.with_lo(after_open).with_hi(before_close)
            } else {
                expr.span
            };
            self.suggest_method_call(
                &mut err,
                "use parentheses to call the method",
                field,
                expr_t,
                expr,
                Some(span),
            );
        } else if let ty::RawPtr(ptr_ty, _) = expr_t.kind()
            && let ty::Adt(adt_def, _) = ptr_ty.kind()
            && let ExprKind::Field(base_expr, _) = expr.kind
            && adt_def.variants().len() == 1
            && adt_def
                .variants()
                .iter()
                .next()
                .unwrap()
                .fields
                .iter()
                .any(|f| f.ident(self.tcx) == field)
        {
            err.multipart_suggestion(
                "to access the field, dereference first",
                vec![
                    (base_expr.span.shrink_to_lo(), "(*".to_string()),
                    (base_expr.span.shrink_to_hi(), ")".to_string()),
                ],
                Applicability::MaybeIncorrect,
            );
        } else {
            err.help("methods are immutable and cannot be assigned to");
        }

        err.emit()
    }

    fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) {
        let generics = self.tcx.generics_of(self.body_id);
        let generic_param = generics.type_param(param, self.tcx);
        if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
            return;
        }
        let param_def_id = generic_param.def_id;
        let param_hir_id = match param_def_id.as_local() {
            Some(x) => self.tcx.local_def_id_to_hir_id(x),
            None => return,
        };
        let param_span = self.tcx.hir().span(param_hir_id);
        let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local());

        err.span_label(param_span, format!("type parameter '{param_name}' declared here"));
    }

    fn maybe_suggest_array_indexing(
        &self,
        err: &mut Diag<'_>,
        expr: &hir::Expr<'_>,
        base: &hir::Expr<'_>,
        field: Ident,
        len: ty::Const<'tcx>,
    ) {
        err.span_label(field.span, "unknown field");
        if let (Some(len), Ok(user_index)) =
            (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
            && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
        {
            let help = "instead of using tuple indexing, use array indexing";
            let suggestion = format!("{base}[{field}]");
            let applicability = if len < user_index {
                Applicability::MachineApplicable
            } else {
                Applicability::MaybeIncorrect
            };
            err.span_suggestion(expr.span, help, suggestion, applicability);
        }
    }

    fn suggest_first_deref_field(
        &self,
        err: &mut Diag<'_>,
        expr: &hir::Expr<'_>,
        base: &hir::Expr<'_>,
        field: Ident,
    ) {
        err.span_label(field.span, "unknown field");
        if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
            let msg = format!("`{base}` is a raw pointer; try dereferencing it");
            let suggestion = format!("(*{base}).{field}");
            err.span_suggestion(expr.span, msg, suggestion, Applicability::MaybeIncorrect);
        }
    }

    fn no_such_field_err(&self, field: Ident, expr_t: Ty<'tcx>, id: HirId) -> Diag<'_> {
        let span = field.span;
        debug!("no_such_field_err(span: {:?}, field: {:?}, expr_t: {:?})", span, field, expr_t);

        let mut err = type_error_struct!(
            self.dcx(),
            span,
            expr_t,
            E0609,
            "no field `{field}` on type `{expr_t}`",
        );

        // try to add a suggestion in case the field is a nested field of a field of the Adt
        let mod_id = self.tcx.parent_module(id).to_def_id();
        let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind()
            && (self.tcx.is_diagnostic_item(sym::Result, def.did())
                || self.tcx.is_diagnostic_item(sym::Option, def.did()))
            && let Some(arg) = args.get(0)
            && let Some(ty) = arg.as_type()
        {
            (ty, "unwrap().")
        } else {
            (expr_t, "")
        };
        for (found_fields, args) in
            self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
        {
            let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
            let mut candidate_fields: Vec<_> = found_fields
                .into_iter()
                .filter_map(|candidate_field| {
                    self.check_for_nested_field_satisfying(
                        span,
                        &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
                        candidate_field,
                        args,
                        vec![],
                        mod_id,
                        id,
                    )
                })
                .map(|mut field_path| {
                    field_path.pop();
                    field_path
                        .iter()
                        .map(|id| format!("{}.", id.name.to_ident_string()))
                        .collect::<String>()
                })
                .collect::<Vec<_>>();
            candidate_fields.sort();

            let len = candidate_fields.len();
            if len > 0 {
                err.span_suggestions(
                    field.span.shrink_to_lo(),
                    format!(
                        "{} of the expressions' fields {} a field of the same name",
                        if len > 1 { "some" } else { "one" },
                        if len > 1 { "have" } else { "has" },
                    ),
                    candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
                    Applicability::MaybeIncorrect,
                );
            } else {
                if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) {
                    err.span_suggestion_verbose(
                        field.span,
                        "a field with a similar name exists",
                        format!("{unwrap}{}", field_name),
                        Applicability::MaybeIncorrect,
                    );
                } else if !field_names.is_empty() {
                    let is = if field_names.len() == 1 { " is" } else { "s are" };
                    err.note(format!(
                        "available field{is}: {}",
                        self.name_series_display(field_names),
                    ));
                }
            }
        }
        err
    }

    fn private_field_err(&self, field: Ident, base_did: DefId) -> Diag<'_> {
        let struct_path = self.tcx().def_path_str(base_did);
        let kind_name = self.tcx().def_descr(base_did);
        struct_span_code_err!(
            self.dcx(),
            field.span,
            E0616,
            "field `{field}` of {kind_name} `{struct_path}` is private",
        )
        .with_span_label(field.span, "private field")
    }

    pub(crate) fn get_field_candidates_considering_privacy(
        &self,
        span: Span,
        base_ty: Ty<'tcx>,
        mod_id: DefId,
        hir_id: HirId,
    ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
        debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);

        self.autoderef(span, base_ty)
            .filter_map(move |(base_t, _)| {
                match base_t.kind() {
                    ty::Adt(base_def, args) if !base_def.is_enum() => {
                        let tcx = self.tcx;
                        let fields = &base_def.non_enum_variant().fields;
                        // Some struct, e.g. some that impl `Deref`, have all private fields
                        // because you're expected to deref them to access the _real_ fields.
                        // This, for example, will help us suggest accessing a field through a `Box<T>`.
                        if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
                            return None;
                        }
                        return Some((
                            fields
                                .iter()
                                .filter(move |field| {
                                    field.vis.is_accessible_from(mod_id, tcx)
                                        && self.is_field_suggestable(field, hir_id, span)
                                })
                                // For compile-time reasons put a limit on number of fields we search
                                .take(100)
                                .collect::<Vec<_>>(),
                            *args,
                        ));
                    }
                    _ => None,
                }
            })
            .collect()
    }

    /// This method is called after we have encountered a missing field error to recursively
    /// search for the field
    pub(crate) fn check_for_nested_field_satisfying(
        &self,
        span: Span,
        matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
        candidate_field: &ty::FieldDef,
        subst: GenericArgsRef<'tcx>,
        mut field_path: Vec<Ident>,
        mod_id: DefId,
        hir_id: HirId,
    ) -> Option<Vec<Ident>> {
        debug!(
            "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
            span, candidate_field, field_path
        );

        if field_path.len() > 3 {
            // For compile-time reasons and to avoid infinite recursion we only check for fields
            // up to a depth of three
            None
        } else {
            field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
            let field_ty = candidate_field.ty(self.tcx, subst);
            if matches(candidate_field, field_ty) {
                return Some(field_path);
            } else {
                for (nested_fields, subst) in
                    self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
                {
                    // recursively search fields of `candidate_field` if it's a ty::Adt
                    for field in nested_fields {
                        if let Some(field_path) = self.check_for_nested_field_satisfying(
                            span,
                            matches,
                            field,
                            subst,
                            field_path.clone(),
                            mod_id,
                            hir_id,
                        ) {
                            return Some(field_path);
                        }
                    }
                }
            }
            None
        }
    }

    fn check_expr_index(
        &self,
        base: &'tcx hir::Expr<'tcx>,
        idx: &'tcx hir::Expr<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
        brackets_span: Span,
    ) -> Ty<'tcx> {
        let base_t = self.check_expr(base);
        let idx_t = self.check_expr(idx);

        if base_t.references_error() {
            base_t
        } else if idx_t.references_error() {
            idx_t
        } else {
            let base_t = self.structurally_resolve_type(base.span, base_t);
            match self.lookup_indexing(expr, base, base_t, idx, idx_t) {
                Some((index_ty, element_ty)) => {
                    // two-phase not needed because index_ty is never mutable
                    self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
                    self.select_obligations_where_possible(|errors| {
                        self.point_at_index(errors, idx.span);
                    });
                    element_ty
                }
                None => {
                    // Attempt to *shallowly* search for an impl which matches,
                    // but has nested obligations which are unsatisfied.
                    for (base_t, _) in self.autoderef(base.span, base_t).silence_errors() {
                        if let Some((_, index_ty, element_ty)) =
                            self.find_and_report_unsatisfied_index_impl(base, base_t)
                        {
                            self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
                            return element_ty;
                        }
                    }

                    let mut err = type_error_struct!(
                        self.dcx(),
                        brackets_span,
                        base_t,
                        E0608,
                        "cannot index into a value of type `{base_t}`",
                    );
                    // Try to give some advice about indexing tuples.
                    if let ty::Tuple(types) = base_t.kind() {
                        let mut needs_note = true;
                        // If the index is an integer, we can show the actual
                        // fixed expression:
                        if let ExprKind::Lit(lit) = idx.kind
                            && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node
                            && i.get()
                                < types
                                    .len()
                                    .try_into()
                                    .expect("expected tuple index to be < usize length")
                        {
                            err.span_suggestion(
                                brackets_span,
                                "to access tuple elements, use",
                                format!(".{i}"),
                                Applicability::MachineApplicable,
                            );
                            needs_note = false;
                        } else if let ExprKind::Path(..) = idx.peel_borrows().kind {
                            err.span_label(
                                idx.span,
                                "cannot access tuple elements at a variable index",
                            );
                        }
                        if needs_note {
                            err.help(
                                "to access tuple elements, use tuple indexing \
                                        syntax (e.g., `tuple.0`)",
                            );
                        }
                    }

                    if base_t.is_unsafe_ptr() && idx_t.is_integral() {
                        err.multipart_suggestion(
                            "consider using `wrapping_add` or `add` for indexing into raw pointer",
                            vec![
                                (base.span.between(idx.span), ".wrapping_add(".to_owned()),
                                (
                                    idx.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
                                    ")".to_owned(),
                                ),
                            ],
                            Applicability::MaybeIncorrect,
                        );
                    }

                    let reported = err.emit();
                    Ty::new_error(self.tcx, reported)
                }
            }
        }
    }

    /// Try to match an implementation of `Index` against a self type, and report
    /// the unsatisfied predicates that result from confirming this impl.
    ///
    /// Given an index expression, sometimes the `Self` type shallowly but does not
    /// deeply satisfy an impl predicate. Instead of simply saying that the type
    /// does not support being indexed, we want to point out exactly what nested
    /// predicates cause this to be, so that the user can add them to fix their code.
    fn find_and_report_unsatisfied_index_impl(
        &self,
        base_expr: &hir::Expr<'_>,
        base_ty: Ty<'tcx>,
    ) -> Option<(ErrorGuaranteed, Ty<'tcx>, Ty<'tcx>)> {
        let index_trait_def_id = self.tcx.lang_items().index_trait()?;
        let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?;

        let mut relevant_impls = vec![];
        self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| {
            relevant_impls.push(impl_def_id);
        });
        let [impl_def_id] = relevant_impls[..] else {
            // Only report unsatisfied impl predicates if there's one impl
            return None;
        };

        self.commit_if_ok(|snapshot| {
            let outer_universe = self.universe();

            let ocx = ObligationCtxt::new(self);
            let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
            let impl_trait_ref =
                self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args);
            let cause = self.misc(base_expr.span);

            // Match the impl self type against the base ty. If this fails,
            // we just skip this impl, since it's not particularly useful.
            let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
            ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?;

            // Register the impl's predicates. One of these predicates
            // must be unsatisfied, or else we wouldn't have gotten here
            // in the first place.
            ocx.register_obligations(traits::predicates_for_generics(
                |idx, span| {
                    cause.clone().derived_cause(
                        ty::Binder::dummy(ty::TraitPredicate {
                            trait_ref: impl_trait_ref,
                            polarity: ty::PredicatePolarity::Positive,
                        }),
                        |derived| {
                            ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
                                derived,
                                impl_or_alias_def_id: impl_def_id,
                                impl_def_predicate_index: Some(idx),
                                span,
                            }))
                        },
                    )
                },
                self.param_env,
                self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args),
            ));

            // Normalize the output type, which we can use later on as the
            // return type of the index expression...
            let element_ty = ocx.normalize(
                &cause,
                self.param_env,
                Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
            );

            let true_errors = ocx.select_where_possible();

            // Do a leak check -- we can't really report report a useful error here,
            // but it at least avoids an ICE when the error has to do with higher-ranked
            // lifetimes.
            self.leak_check(outer_universe, Some(snapshot))?;

            // Bail if we have ambiguity errors, which we can't report in a useful way.
            let ambiguity_errors = ocx.select_all_or_error();
            if true_errors.is_empty() && !ambiguity_errors.is_empty() {
                return Err(NoSolution);
            }

            // There should be at least one error reported. If not, we
            // will still delay a span bug in `report_fulfillment_errors`.
            Ok::<_, NoSolution>((
                self.err_ctxt().report_fulfillment_errors(true_errors),
                impl_trait_ref.args.type_at(1),
                element_ty,
            ))
        })
        .ok()
    }

    fn point_at_index(&self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, span: Span) {
        let mut seen_preds = FxHashSet::default();
        // We re-sort here so that the outer most root obligations comes first, as we have the
        // subsequent weird logic to identify *every* relevant obligation for proper deduplication
        // of diagnostics.
        errors.sort_by_key(|error| error.root_obligation.recursion_depth);
        for error in errors {
            match (
                error.root_obligation.predicate.kind().skip_binder(),
                error.obligation.predicate.kind().skip_binder(),
            ) {
                (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _)
                    if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) =>
                {
                    seen_preds.insert(error.obligation.predicate.kind().skip_binder());
                }
                (_, ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)))
                    if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) =>
                {
                    seen_preds.insert(error.obligation.predicate.kind().skip_binder());
                }
                (root, pred) if seen_preds.contains(&pred) || seen_preds.contains(&root) => {}
                _ => continue,
            }
            error.obligation.cause.span = span;
        }
    }

    fn check_expr_yield(
        &self,
        value: &'tcx hir::Expr<'tcx>,
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        match self.coroutine_types {
            Some(CoroutineTypes { resume_ty, yield_ty }) => {
                self.check_expr_coercible_to_type(value, yield_ty, None);

                resume_ty
            }
            _ => {
                self.dcx().emit_err(YieldExprOutsideOfCoroutine { span: expr.span });
                // Avoid expressions without types during writeback (#78653).
                self.check_expr(value);
                self.tcx.types.unit
            }
        }
    }

    fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) {
        let needs = if is_input { Needs::None } else { Needs::MutPlace };
        let ty = self.check_expr_with_needs(expr, needs);
        self.require_type_is_sized(ty, expr.span, ObligationCauseCode::InlineAsmSized);

        if !is_input && !expr.is_syntactic_place_expr() {
            self.dcx()
                .struct_span_err(expr.span, "invalid asm output")
                .with_span_label(expr.span, "cannot assign to this expression")
                .emit();
        }

        // If this is an input value, we require its type to be fully resolved
        // at this point. This allows us to provide helpful coercions which help
        // pass the type candidate list in a later pass.
        //
        // We don't require output types to be resolved at this point, which
        // allows them to be inferred based on how they are used later in the
        // function.
        if is_input {
            let ty = self.structurally_resolve_type(expr.span, ty);
            match *ty.kind() {
                ty::FnDef(..) => {
                    let fnptr_ty = Ty::new_fn_ptr(self.tcx, ty.fn_sig(self.tcx));
                    self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No);
                }
                ty::Ref(_, base_ty, mutbl) => {
                    let ptr_ty = Ty::new_ptr(self.tcx, base_ty, mutbl);
                    self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No);
                }
                _ => {}
            }
        }
    }

    fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
        let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN);

        for (op, _op_sp) in asm.operands {
            match op {
                hir::InlineAsmOperand::In { expr, .. } => {
                    self.check_expr_asm_operand(expr, true);
                }
                hir::InlineAsmOperand::Out { expr: Some(expr), .. }
                | hir::InlineAsmOperand::InOut { expr, .. } => {
                    self.check_expr_asm_operand(expr, false);
                }
                hir::InlineAsmOperand::Out { expr: None, .. } => {}
                hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                    self.check_expr_asm_operand(in_expr, true);
                    if let Some(out_expr) = out_expr {
                        self.check_expr_asm_operand(out_expr, false);
                    }
                }
                // `AnonConst`s have their own body and is type-checked separately.
                // As they don't flow into the type system we don't need them to
                // be well-formed.
                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
                hir::InlineAsmOperand::SymStatic { .. } => {}
                hir::InlineAsmOperand::Label { block } => {
                    let previous_diverges = self.diverges.get();

                    // The label blocks should have unit return value or diverge.
                    let ty =
                        self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
                    if !ty.is_never() {
                        self.demand_suptype(block.span, self.tcx.types.unit, ty);
                        diverge = false;
                    }

                    // We need this to avoid false unreachable warning when a label diverges.
                    self.diverges.set(previous_diverges);
                }
            }
        }

        if diverge { self.tcx.types.never } else { self.tcx.types.unit }
    }

    fn check_offset_of(
        &self,
        container: &'tcx hir::Ty<'tcx>,
        fields: &[Ident],
        expr: &'tcx hir::Expr<'tcx>,
    ) -> Ty<'tcx> {
        let container = self.lower_ty(container).normalized;

        if let Some(ident_2) = fields.get(1)
            && !self.tcx.features().offset_of_nested
        {
            rustc_session::parse::feature_err(
                &self.tcx.sess,
                sym::offset_of_nested,
                ident_2.span,
                "only a single ident or integer is stable as the field in offset_of",
            )
            .emit();
        }

        let mut field_indices = Vec::with_capacity(fields.len());
        let mut current_container = container;
        let mut fields = fields.into_iter();

        while let Some(&field) = fields.next() {
            let container = self.structurally_resolve_type(expr.span, current_container);

            match container.kind() {
                ty::Adt(container_def, args) if container_def.is_enum() => {
                    let block = self.tcx.local_def_id_to_hir_id(self.body_id);
                    let (ident, _def_scope) =
                        self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);

                    if !self.tcx.features().offset_of_enum {
                        rustc_session::parse::feature_err(
                            &self.tcx.sess,
                            sym::offset_of_enum,
                            ident.span,
                            "using enums in offset_of is experimental",
                        )
                        .emit();
                    }

                    let Some((index, variant)) = container_def
                        .variants()
                        .iter_enumerated()
                        .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
                    else {
                        type_error_struct!(
                            self.dcx(),
                            ident.span,
                            container,
                            E0599,
                            "no variant named `{ident}` found for enum `{container}`",
                        )
                        .with_span_label(field.span, "variant not found")
                        .emit();
                        break;
                    };
                    let Some(&subfield) = fields.next() else {
                        type_error_struct!(
                            self.dcx(),
                            ident.span,
                            container,
                            E0795,
                            "`{ident}` is an enum variant; expected field at end of `offset_of`",
                        )
                        .with_span_label(field.span, "enum variant")
                        .emit();
                        break;
                    };
                    let (subident, sub_def_scope) =
                        self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block);

                    let Some((subindex, field)) = variant
                        .fields
                        .iter_enumerated()
                        .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident)
                    else {
                        type_error_struct!(
                            self.dcx(),
                            ident.span,
                            container,
                            E0609,
                            "no field named `{subfield}` on enum variant `{container}::{ident}`",
                        )
                        .with_span_label(field.span, "this enum variant...")
                        .with_span_label(subident.span, "...does not have this field")
                        .emit();
                        break;
                    };

                    let field_ty = self.field_ty(expr.span, field, args);

                    // FIXME: DSTs with static alignment should be allowed
                    self.require_type_is_sized(field_ty, expr.span, ObligationCauseCode::Misc);

                    if field.vis.is_accessible_from(sub_def_scope, self.tcx) {
                        self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
                    } else {
                        self.private_field_err(ident, container_def.did()).emit();
                    }

                    // Save the index of all fields regardless of their visibility in case
                    // of error recovery.
                    field_indices.push((index, subindex));
                    current_container = field_ty;

                    continue;
                }
                ty::Adt(container_def, args) => {
                    let block = self.tcx.local_def_id_to_hir_id(self.body_id);
                    let (ident, def_scope) =
                        self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);

                    let fields = &container_def.non_enum_variant().fields;
                    if let Some((index, field)) = fields
                        .iter_enumerated()
                        .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident)
                    {
                        let field_ty = self.field_ty(expr.span, field, args);

                        // FIXME: DSTs with static alignment should be allowed
                        self.require_type_is_sized(field_ty, expr.span, ObligationCauseCode::Misc);

                        if field.vis.is_accessible_from(def_scope, self.tcx) {
                            self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
                        } else {
                            self.private_field_err(ident, container_def.did()).emit();
                        }

                        // Save the index of all fields regardless of their visibility in case
                        // of error recovery.
                        field_indices.push((FIRST_VARIANT, index));
                        current_container = field_ty;

                        continue;
                    }
                }
                ty::Tuple(tys) => {
                    if let Ok(index) = field.as_str().parse::<usize>()
                        && field.name == sym::integer(index)
                    {
                        for ty in tys.iter().take(index + 1) {
                            self.require_type_is_sized(ty, expr.span, ObligationCauseCode::Misc);
                        }
                        if let Some(&field_ty) = tys.get(index) {
                            field_indices.push((FIRST_VARIANT, index.into()));
                            current_container = field_ty;

                            continue;
                        }
                    }
                }
                _ => (),
            };

            self.no_such_field_err(field, container, expr.hir_id).emit();

            break;
        }

        self.typeck_results
            .borrow_mut()
            .offset_of_data_mut()
            .insert(expr.hir_id, (container, field_indices));

        self.tcx.types.usize
    }
}
