// ignore-tidy-filelength

#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]

use either::Either;
use hir::ClosureKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Map, Visitor};
use rustc_hir::{CoroutineDesugaring, PatField};
use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
    self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
    FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
    Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
    TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{
    self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
    TypeSuperVisitable, TypeVisitor,
};
use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::DefId;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
use std::iter;

use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
use crate::{
    borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
    InitializationRequiringAction, MirBorrowckCtxt, WriteKind,
};

use super::{
    explain_borrow::{BorrowExplanation, LaterUseKind},
    DescribePlaceOpt, RegionName, RegionNameSource, UseSpans,
};

#[derive(Debug)]
struct MoveSite {
    /// Index of the "move out" that we found. The `MoveData` can
    /// then tell us where the move occurred.
    moi: MoveOutIndex,

    /// `true` if we traversed a back edge while walking from the point
    /// of error to the move site.
    traversed_back_edge: bool,
}

/// Which case a StorageDeadOrDrop is for.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum StorageDeadOrDrop<'tcx> {
    LocalStorageDead,
    BoxedStorageDead,
    Destructor(Ty<'tcx>),
}

impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
    pub(crate) fn report_use_of_moved_or_uninitialized(
        &mut self,
        location: Location,
        desired_action: InitializationRequiringAction,
        (moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span),
        mpi: MovePathIndex,
    ) {
        debug!(
            "report_use_of_moved_or_uninitialized: location={:?} desired_action={:?} \
             moved_place={:?} used_place={:?} span={:?} mpi={:?}",
            location, desired_action, moved_place, used_place, span, mpi
        );

        let use_spans =
            self.move_spans(moved_place, location).or_else(|| self.borrow_spans(span, location));
        let span = use_spans.args_or_use();

        let (move_site_vec, maybe_reinitialized_locations) = self.get_moved_indexes(location, mpi);
        debug!(
            "report_use_of_moved_or_uninitialized: move_site_vec={:?} use_spans={:?}",
            move_site_vec, use_spans
        );
        let move_out_indices: Vec<_> =
            move_site_vec.iter().map(|move_site| move_site.moi).collect();

        if move_out_indices.is_empty() {
            let root_place = PlaceRef { projection: &[], ..used_place };

            if !self.uninitialized_error_reported.insert(root_place) {
                debug!(
                    "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
                    root_place
                );
                return;
            }

            let err = self.report_use_of_uninitialized(
                mpi,
                used_place,
                moved_place,
                desired_action,
                span,
                use_spans,
            );
            self.buffer_error(err);
        } else {
            if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) {
                if used_place.is_prefix_of(*reported_place) {
                    debug!(
                        "report_use_of_moved_or_uninitialized place: error suppressed mois={:?}",
                        move_out_indices
                    );
                    return;
                }
            }

            let is_partial_move = move_site_vec.iter().any(|move_site| {
                let move_out = self.move_data.moves[(*move_site).moi];
                let moved_place = &self.move_data.move_paths[move_out.path].place;
                // `*(_1)` where `_1` is a `Box` is actually a move out.
                let is_box_move = moved_place.as_ref().projection == [ProjectionElem::Deref]
                    && self.body.local_decls[moved_place.local].ty.is_box();

                !is_box_move
                    && used_place != moved_place.as_ref()
                    && used_place.is_prefix_of(moved_place.as_ref())
            });

            let partial_str = if is_partial_move { "partial " } else { "" };
            let partially_str = if is_partial_move { "partially " } else { "" };

            let mut err = self.cannot_act_on_moved_value(
                span,
                desired_action.as_noun(),
                partially_str,
                self.describe_place_with_options(
                    moved_place,
                    DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
                ),
            );

            let reinit_spans = maybe_reinitialized_locations
                .iter()
                .take(3)
                .map(|loc| {
                    self.move_spans(self.move_data.move_paths[mpi].place.as_ref(), *loc)
                        .args_or_use()
                })
                .collect::<Vec<Span>>();

            let reinits = maybe_reinitialized_locations.len();
            if reinits == 1 {
                err.span_label(reinit_spans[0], "this reinitialization might get skipped");
            } else if reinits > 1 {
                err.span_note(
                    MultiSpan::from_spans(reinit_spans),
                    if reinits <= 3 {
                        format!("these {reinits} reinitializations might get skipped")
                    } else {
                        format!(
                            "these 3 reinitializations and {} other{} might get skipped",
                            reinits - 3,
                            if reinits == 4 { "" } else { "s" }
                        )
                    },
                );
            }

            let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err);

            let mut is_loop_move = false;
            let mut in_pattern = false;
            let mut seen_spans = FxIndexSet::default();

            for move_site in &move_site_vec {
                let move_out = self.move_data.moves[(*move_site).moi];
                let moved_place = &self.move_data.move_paths[move_out.path].place;

                let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
                let move_span = move_spans.args_or_use();

                let is_move_msg = move_spans.for_closure();

                let is_loop_message = location == move_out.source || move_site.traversed_back_edge;

                if location == move_out.source {
                    is_loop_move = true;
                }

                if !seen_spans.contains(&move_span) {
                    if !closure {
                        self.suggest_ref_or_clone(mpi, &mut err, &mut in_pattern, move_spans);
                    }

                    let msg_opt = CapturedMessageOpt {
                        is_partial_move,
                        is_loop_message,
                        is_move_msg,
                        is_loop_move,
                        maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
                            .is_empty(),
                    };
                    self.explain_captures(
                        &mut err,
                        span,
                        move_span,
                        move_spans,
                        *moved_place,
                        msg_opt,
                    );
                }
                seen_spans.insert(move_span);
            }

            use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);

            if !is_loop_move {
                err.span_label(
                    span,
                    format!(
                        "value {} here after {partial_str}move",
                        desired_action.as_verb_in_past_tense(),
                    ),
                );
            }

            let ty = used_place.ty(self.body, self.infcx.tcx).ty;
            let needs_note = match ty.kind() {
                ty::Closure(id, _) => {
                    self.infcx.tcx.closure_kind_origin(id.expect_local()).is_none()
                }
                _ => true,
            };

            let mpi = self.move_data.moves[move_out_indices[0]].path;
            let place = &self.move_data.move_paths[mpi].place;
            let ty = place.ty(self.body, self.infcx.tcx).ty;

            // If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
            // Same for if we're in a loop, see #101119.
            if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
                if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
                    // We have a `&mut` ref, we need to reborrow on each iteration (#62112).
                    err.span_suggestion_verbose(
                        span.shrink_to_lo(),
                        format!(
                            "consider creating a fresh reborrow of {} here",
                            self.describe_place(moved_place)
                                .map(|n| format!("`{n}`"))
                                .unwrap_or_else(|| "the mutable reference".to_string()),
                        ),
                        "&mut *",
                        Applicability::MachineApplicable,
                    );
                }
            }

            let opt_name = self.describe_place_with_options(
                place.as_ref(),
                DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
            );
            let note_msg = match opt_name {
                Some(name) => format!("`{name}`"),
                None => "value".to_owned(),
            };
            if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, &note_msg)
                || if let UseSpans::FnSelfUse { kind, .. } = use_spans
                    && let CallKind::FnCall { fn_trait_id, self_ty } = kind
                    && let ty::Param(_) = self_ty.kind()
                    && ty == self_ty
                    && Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait()
                {
                    // this is a type parameter `T: FnOnce()`, don't suggest `T: FnOnce() + Clone`.
                    true
                } else {
                    false
                }
            {
                // Suppress the next suggestion since we don't want to put more bounds onto
                // something that already has `Fn`-like bounds (or is a closure), so we can't
                // restrict anyways.
            } else {
                let copy_did = self.infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
                self.suggest_adding_bounds(&mut err, ty, copy_did, span);
            }

            if needs_note {
                if let Some(local) = place.as_local() {
                    let span = self.body.local_decls[local].source_info.span;
                    err.subdiagnostic(
                        self.dcx(),
                        crate::session_diagnostics::TypeNoCopy::Label {
                            is_partial_move,
                            ty,
                            place: &note_msg,
                            span,
                        },
                    );
                } else {
                    err.subdiagnostic(
                        self.dcx(),
                        crate::session_diagnostics::TypeNoCopy::Note {
                            is_partial_move,
                            ty,
                            place: &note_msg,
                        },
                    );
                };
            }

            if let UseSpans::FnSelfUse {
                kind: CallKind::DerefCoercion { deref_target, deref_target_ty, .. },
                ..
            } = use_spans
            {
                err.note(format!(
                    "{} occurs due to deref coercion to `{deref_target_ty}`",
                    desired_action.as_noun(),
                ));

                // Check first whether the source is accessible (issue #87060)
                if self.infcx.tcx.sess.source_map().is_span_accessible(deref_target) {
                    err.span_note(deref_target, "deref defined here");
                }
            }

            self.buffer_move_error(move_out_indices, (used_place, err));
        }
    }

    fn suggest_ref_or_clone(
        &self,
        mpi: MovePathIndex,
        err: &mut Diag<'tcx>,
        in_pattern: &mut bool,
        move_spans: UseSpans<'tcx>,
    ) {
        let move_span = match move_spans {
            UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
            _ => move_spans.args_or_use(),
        };
        struct ExpressionFinder<'hir> {
            expr_span: Span,
            expr: Option<&'hir hir::Expr<'hir>>,
            pat: Option<&'hir hir::Pat<'hir>>,
            parent_pat: Option<&'hir hir::Pat<'hir>>,
            hir: rustc_middle::hir::map::Map<'hir>,
        }
        impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
            type NestedFilter = OnlyBodies;

            fn nested_visit_map(&mut self) -> Self::Map {
                self.hir
            }

            fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
                if e.span == self.expr_span {
                    self.expr = Some(e);
                }
                hir::intravisit::walk_expr(self, e);
            }
            fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
                if p.span == self.expr_span {
                    self.pat = Some(p);
                }
                if let hir::PatKind::Binding(hir::BindingMode::NONE, _, i, sub) = p.kind {
                    if i.span == self.expr_span || p.span == self.expr_span {
                        self.pat = Some(p);
                    }
                    // Check if we are in a situation of `ident @ ident` where we want to suggest
                    // `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`.
                    if let Some(subpat) = sub
                        && self.pat.is_none()
                    {
                        self.visit_pat(subpat);
                        if self.pat.is_some() {
                            self.parent_pat = Some(p);
                        }
                        return;
                    }
                }
                hir::intravisit::walk_pat(self, p);
            }
        }
        let hir = self.infcx.tcx.hir();
        if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) {
            let expr = hir.body(body_id).value;
            let place = &self.move_data.move_paths[mpi].place;
            let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span);
            let mut finder = ExpressionFinder {
                expr_span: move_span,
                expr: None,
                pat: None,
                parent_pat: None,
                hir,
            };
            finder.visit_expr(expr);
            if let Some(span) = span
                && let Some(expr) = finder.expr
            {
                for (_, expr) in hir.parent_iter(expr.hir_id) {
                    if let hir::Node::Expr(expr) = expr {
                        if expr.span.contains(span) {
                            // If the let binding occurs within the same loop, then that
                            // loop isn't relevant, like in the following, the outermost `loop`
                            // doesn't play into `x` being moved.
                            // ```
                            // loop {
                            //     let x = String::new();
                            //     loop {
                            //         foo(x);
                            //     }
                            // }
                            // ```
                            break;
                        }
                        if let hir::ExprKind::Loop(.., loop_span) = expr.kind {
                            err.span_label(loop_span, "inside of this loop");
                        }
                    }
                }
                let typeck = self.infcx.tcx.typeck(self.mir_def_id());
                let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
                let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
                    && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
                    && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
                {
                    (def_id.as_local(), args, 1)
                } else if let hir::Node::Expr(parent_expr) = parent
                    && let hir::ExprKind::Call(call, args) = parent_expr.kind
                    && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
                {
                    (def_id.as_local(), args, 0)
                } else {
                    (None, &[][..], 0)
                };
                if let Some(def_id) = def_id
                    && let node = self.infcx.tcx.hir_node_by_def_id(def_id)
                    && let Some(fn_sig) = node.fn_sig()
                    && let Some(ident) = node.ident()
                    && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
                    && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
                {
                    let mut span: MultiSpan = arg.span.into();
                    span.push_span_label(
                        arg.span,
                        "this parameter takes ownership of the value".to_string(),
                    );
                    let descr = match node.fn_kind() {
                        Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
                        Some(hir::intravisit::FnKind::Method(..)) => "method",
                        Some(hir::intravisit::FnKind::Closure) => "closure",
                    };
                    span.push_span_label(ident.span, format!("in this {descr}"));
                    err.span_note(
                        span,
                        format!(
                            "consider changing this parameter type in {descr} `{ident}` to borrow \
                             instead if owning the value isn't necessary",
                        ),
                    );
                }
                let place = &self.move_data.move_paths[mpi].place;
                let ty = place.ty(self.body, self.infcx.tcx).ty;
                if let hir::Node::Expr(parent_expr) = parent
                    && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
                    && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
                        call_expr.kind
                {
                    // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
                } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
                {
                    // We already suggest cloning for these cases in `explain_captures`.
                } else if let UseSpans::ClosureUse {
                    closure_kind:
                        ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),
                    ..
                } = move_spans
                {
                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                } else if self.suggest_hoisting_call_outside_loop(err, expr) {
                    // The place where the type moves would be misleading to suggest clone.
                    // #121466
                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
                }
            }
            if let Some(pat) = finder.pat {
                *in_pattern = true;
                let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
                if let Some(pat) = finder.parent_pat {
                    sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
                }
                err.multipart_suggestion_verbose(
                    "borrow this binding in the pattern to avoid moving the value",
                    sugg,
                    Applicability::MachineApplicable,
                );
            }
        }
    }

    fn report_use_of_uninitialized(
        &self,
        mpi: MovePathIndex,
        used_place: PlaceRef<'tcx>,
        moved_place: PlaceRef<'tcx>,
        desired_action: InitializationRequiringAction,
        span: Span,
        use_spans: UseSpans<'tcx>,
    ) -> Diag<'tcx> {
        // We need all statements in the body where the binding was assigned to later find all
        // the branching code paths where the binding *wasn't* assigned to.
        let inits = &self.move_data.init_path_map[mpi];
        let move_path = &self.move_data.move_paths[mpi];
        let decl_span = self.body.local_decls[move_path.place.local].source_info.span;
        let mut spans = vec![];
        for init_idx in inits {
            let init = &self.move_data.inits[*init_idx];
            let span = init.span(self.body);
            if !span.is_dummy() {
                spans.push(span);
            }
        }

        let (name, desc) = match self.describe_place_with_options(
            moved_place,
            DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
        ) {
            Some(name) => (format!("`{name}`"), format!("`{name}` ")),
            None => ("the variable".to_string(), String::new()),
        };
        let path = match self.describe_place_with_options(
            used_place,
            DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
        ) {
            Some(name) => format!("`{name}`"),
            None => "value".to_string(),
        };

        // We use the statements were the binding was initialized, and inspect the HIR to look
        // for the branching codepaths that aren't covered, to point at them.
        let map = self.infcx.tcx.hir();
        let body_id = map.body_owned_by(self.mir_def_id());
        let body = map.body(body_id);

        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
        visitor.visit_body(body);

        let mut show_assign_sugg = false;
        let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
        | InitializationRequiringAction::Assignment = desired_action
        {
            // The same error is emitted for bindings that are *sometimes* initialized and the ones
            // that are *partially* initialized by assigning to a field of an uninitialized
            // binding. We differentiate between them for more accurate wording here.
            "isn't fully initialized"
        } else if !spans.iter().any(|i| {
            // We filter these to avoid misleading wording in cases like the following,
            // where `x` has an `init`, but it is in the same place we're looking at:
            // ```
            // let x;
            // x += 1;
            // ```
            !i.contains(span)
            // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
            && !visitor
                .errors
                .iter()
                .map(|(sp, _)| *sp)
                .any(|sp| span < sp && !sp.contains(span))
        }) {
            show_assign_sugg = true;
            "isn't initialized"
        } else {
            "is possibly-uninitialized"
        };

        let used = desired_action.as_general_verb_in_past_tense();
        let mut err = struct_span_code_err!(
            self.dcx(),
            span,
            E0381,
            "{used} binding {desc}{isnt_initialized}"
        );
        use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);

        if let InitializationRequiringAction::PartialAssignment
        | InitializationRequiringAction::Assignment = desired_action
        {
            err.help(
                "partial initialization isn't supported, fully initialize the binding with a \
                 default value and mutate it, or use `std::mem::MaybeUninit`",
            );
        }
        err.span_label(span, format!("{path} {used} here but it {isnt_initialized}"));

        let mut shown = false;
        for (sp, label) in visitor.errors {
            if sp < span && !sp.overlaps(span) {
                // When we have a case like `match-cfg-fake-edges.rs`, we don't want to mention
                // match arms coming after the primary span because they aren't relevant:
                // ```
                // let x;
                // match y {
                //     _ if { x = 2; true } => {}
                //     _ if {
                //         x; //~ ERROR
                //         false
                //     } => {}
                //     _ => {} // We don't want to point to this.
                // };
                // ```
                err.span_label(sp, label);
                shown = true;
            }
        }
        if !shown {
            for sp in &spans {
                if *sp < span && !sp.overlaps(span) {
                    err.span_label(*sp, "binding initialized here in some conditions");
                }
            }
        }

        err.span_label(decl_span, "binding declared here but left uninitialized");
        if show_assign_sugg {
            struct LetVisitor {
                decl_span: Span,
                sugg_span: Option<Span>,
            }

            impl<'v> Visitor<'v> for LetVisitor {
                fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
                    if self.sugg_span.is_some() {
                        return;
                    }

                    // FIXME: We make sure that this is a normal top-level binding,
                    // but we could suggest `todo!()` for all uninitialized bindings in the pattern pattern
                    if let hir::StmtKind::Let(hir::LetStmt { span, ty, init: None, pat, .. }) =
                        &ex.kind
                        && let hir::PatKind::Binding(..) = pat.kind
                        && span.contains(self.decl_span)
                    {
                        self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
                    }
                    hir::intravisit::walk_stmt(self, ex);
                }
            }

            let mut visitor = LetVisitor { decl_span, sugg_span: None };
            visitor.visit_body(body);
            if let Some(span) = visitor.sugg_span {
                self.suggest_assign_value(&mut err, moved_place, span);
            }
        }
        err
    }

    fn suggest_assign_value(
        &self,
        err: &mut Diag<'_>,
        moved_place: PlaceRef<'tcx>,
        sugg_span: Span,
    ) {
        let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
        debug!("ty: {:?}, kind: {:?}", ty, ty.kind());

        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
        else {
            return;
        };

        err.span_suggestion_verbose(
            sugg_span.shrink_to_hi(),
            "consider assigning a value",
            format!(" = {assign_value}"),
            Applicability::MaybeIncorrect,
        );
    }

    fn suggest_borrow_fn_like(
        &self,
        err: &mut Diag<'_>,
        ty: Ty<'tcx>,
        move_sites: &[MoveSite],
        value_name: &str,
    ) -> bool {
        let tcx = self.infcx.tcx;

        // Find out if the predicates show that the type is a Fn or FnMut
        let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| {
            if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
                && pred.self_ty() == ty
            {
                if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
                    return Some(hir::Mutability::Not);
                } else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
                    return Some(hir::Mutability::Mut);
                }
            }
            None
        };

        // If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
        // borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
        // These types seem reasonably opaque enough that they could be instantiated with their
        // borrowed variants in a function body when we see a move error.
        let borrow_level = match *ty.kind() {
            ty::Param(_) => tcx
                .explicit_predicates_of(self.mir_def_id().to_def_id())
                .predicates
                .iter()
                .copied()
                .find_map(find_fn_kind_from_did),
            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
                .explicit_item_super_predicates(def_id)
                .iter_instantiated_copied(tcx, args)
                .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
            ty::Closure(_, args) => match args.as_closure().kind() {
                ty::ClosureKind::Fn => Some(hir::Mutability::Not),
                ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
                _ => None,
            },
            _ => None,
        };

        let Some(borrow_level) = borrow_level else {
            return false;
        };
        let sugg = move_sites
            .iter()
            .map(|move_site| {
                let move_out = self.move_data.moves[(*move_site).moi];
                let moved_place = &self.move_data.move_paths[move_out.path].place;
                let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
                let move_span = move_spans.args_or_use();
                let suggestion = borrow_level.ref_prefix_str().to_owned();
                (move_span.shrink_to_lo(), suggestion)
            })
            .collect();
        err.multipart_suggestion_verbose(
            format!("consider {}borrowing {value_name}", borrow_level.mutably_str()),
            sugg,
            Applicability::MaybeIncorrect,
        );
        true
    }

    /// In a move error that occurs on a call within a loop, we try to identify cases where cloning
    /// the value would lead to a logic error. We infer these cases by seeing if the moved value is
    /// part of the logic to break the loop, either through an explicit `break` or if the expression
    /// is part of a `while let`.
    fn suggest_hoisting_call_outside_loop(&self, err: &mut Diag<'_>, expr: &hir::Expr<'_>) -> bool {
        let tcx = self.infcx.tcx;
        let mut can_suggest_clone = true;

        // If the moved value is a locally declared binding, we'll look upwards on the expression
        // tree until the scope where it is defined, and no further, as suggesting to move the
        // expression beyond that point would be illogical.
        let local_hir_id = if let hir::ExprKind::Path(hir::QPath::Resolved(
            _,
            hir::Path { res: hir::def::Res::Local(local_hir_id), .. },
        )) = expr.kind
        {
            Some(local_hir_id)
        } else {
            // This case would be if the moved value comes from an argument binding, we'll just
            // look within the entire item, that's fine.
            None
        };

        /// This will allow us to look for a specific `HirId`, in our case `local_hir_id` where the
        /// binding was declared, within any other expression. We'll use it to search for the
        /// binding declaration within every scope we inspect.
        struct Finder {
            hir_id: hir::HirId,
            found: bool,
        }
        impl<'hir> Visitor<'hir> for Finder {
            fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) {
                if pat.hir_id == self.hir_id {
                    self.found = true;
                }
                hir::intravisit::walk_pat(self, pat);
            }
            fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
                if ex.hir_id == self.hir_id {
                    self.found = true;
                }
                hir::intravisit::walk_expr(self, ex);
            }
        }
        // The immediate HIR parent of the moved expression. We'll look for it to be a call.
        let mut parent = None;
        // The top-most loop where the moved expression could be moved to a new binding.
        let mut outer_most_loop: Option<&hir::Expr<'_>> = None;
        for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
            let e = match node {
                hir::Node::Expr(e) => e,
                hir::Node::LetStmt(hir::LetStmt { els: Some(els), .. }) => {
                    let mut finder = BreakFinder { found_breaks: vec![], found_continues: vec![] };
                    finder.visit_block(els);
                    if !finder.found_breaks.is_empty() {
                        // Don't suggest clone as it could be will likely end in an infinite
                        // loop.
                        // let Some(_) = foo(non_copy.clone()) else { break; }
                        // ---                       ^^^^^^^^         -----
                        can_suggest_clone = false;
                    }
                    continue;
                }
                _ => continue,
            };
            if let Some(&hir_id) = local_hir_id {
                let mut finder = Finder { hir_id, found: false };
                finder.visit_expr(e);
                if finder.found {
                    // The current scope includes the declaration of the binding we're accessing, we
                    // can't look up any further for loops.
                    break;
                }
            }
            if parent.is_none() {
                parent = Some(e);
            }
            match e.kind {
                hir::ExprKind::Let(_) => {
                    match tcx.parent_hir_node(e.hir_id) {
                        hir::Node::Expr(hir::Expr {
                            kind: hir::ExprKind::If(cond, ..), ..
                        }) => {
                            let mut finder = Finder { hir_id: expr.hir_id, found: false };
                            finder.visit_expr(cond);
                            if finder.found {
                                // The expression where the move error happened is in a `while let`
                                // condition Don't suggest clone as it will likely end in an
                                // infinite loop.
                                // while let Some(_) = foo(non_copy.clone()) { }
                                // ---------                       ^^^^^^^^
                                can_suggest_clone = false;
                            }
                        }
                        _ => {}
                    }
                }
                hir::ExprKind::Loop(..) => {
                    outer_most_loop = Some(e);
                }
                _ => {}
            }
        }
        let loop_count: usize = tcx
            .hir()
            .parent_iter(expr.hir_id)
            .map(|(_, node)| match node {
                hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Loop(..), .. }) => 1,
                _ => 0,
            })
            .sum();

        let sm = tcx.sess.source_map();
        if let Some(in_loop) = outer_most_loop {
            let mut finder = BreakFinder { found_breaks: vec![], found_continues: vec![] };
            finder.visit_expr(in_loop);
            // All of the spans for `break` and `continue` expressions.
            let spans = finder
                .found_breaks
                .iter()
                .chain(finder.found_continues.iter())
                .map(|(_, span)| *span)
                .filter(|span| {
                    !matches!(
                        span.desugaring_kind(),
                        Some(DesugaringKind::ForLoop | DesugaringKind::WhileLoop)
                    )
                })
                .collect::<Vec<Span>>();
            // All of the spans for the loops above the expression with the move error.
            let loop_spans: Vec<_> = tcx
                .hir()
                .parent_iter(expr.hir_id)
                .filter_map(|(_, node)| match node {
                    hir::Node::Expr(hir::Expr { span, kind: hir::ExprKind::Loop(..), .. }) => {
                        Some(*span)
                    }
                    _ => None,
                })
                .collect();
            // It is possible that a user written `break` or `continue` is in the wrong place. We
            // point them out at the user for them to make a determination. (#92531)
            if !spans.is_empty() && loop_count > 1 {
                // Getting fancy: if the spans of the loops *do not* overlap, we only use the line
                // number when referring to them. If there *are* overlaps (multiple loops on the
                // same line) then we use the more verbose span output (`file.rs:col:ll`).
                let mut lines: Vec<_> =
                    loop_spans.iter().map(|sp| sm.lookup_char_pos(sp.lo()).line).collect();
                lines.sort();
                lines.dedup();
                let fmt_span = |span: Span| {
                    if lines.len() == loop_spans.len() {
                        format!("line {}", sm.lookup_char_pos(span.lo()).line)
                    } else {
                        sm.span_to_diagnostic_string(span)
                    }
                };
                let mut spans: MultiSpan = spans.into();
                // Point at all the `continue`s and explicit `break`s in the relevant loops.
                for (desc, elements) in [
                    ("`break` exits", &finder.found_breaks),
                    ("`continue` advances", &finder.found_continues),
                ] {
                    for (destination, sp) in elements {
                        if let Ok(hir_id) = destination.target_id
                            && let hir::Node::Expr(expr) = tcx.hir().hir_node(hir_id)
                            && !matches!(
                                sp.desugaring_kind(),
                                Some(DesugaringKind::ForLoop | DesugaringKind::WhileLoop)
                            )
                        {
                            spans.push_span_label(
                                *sp,
                                format!("this {desc} the loop at {}", fmt_span(expr.span)),
                            );
                        }
                    }
                }
                // Point at all the loops that are between this move and the parent item.
                for span in loop_spans {
                    spans.push_span_label(sm.guess_head_span(span), "");
                }

                // note: verify that your loop breaking logic is correct
                //   --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
                //    |
                // 28 |     for foo in foos {
                //    |     ---------------
                // ...
                // 33 |         for bar in &bars {
                //    |         ----------------
                // ...
                // 41 |                 continue;
                //    |                 ^^^^^^^^ this `continue` advances the loop at line 33
                err.span_note(spans, "verify that your loop breaking logic is correct");
            }
            if let Some(parent) = parent
                && let hir::ExprKind::MethodCall(..) | hir::ExprKind::Call(..) = parent.kind
            {
                // FIXME: We could check that the call's *parent* takes `&mut val` to make the
                // suggestion more targeted to the `mk_iter(val).next()` case. Maybe do that only to
                // check for whether to suggest `let value` or `let mut value`.

                let span = in_loop.span;
                if !finder.found_breaks.is_empty()
                    && let Ok(value) = sm.span_to_snippet(parent.span)
                {
                    // We know with high certainty that this move would affect the early return of a
                    // loop, so we suggest moving the expression with the move out of the loop.
                    let indent = if let Some(indent) = sm.indentation_before(span) {
                        format!("\n{indent}")
                    } else {
                        " ".to_string()
                    };
                    err.multipart_suggestion(
                        "consider moving the expression out of the loop so it is only moved once",
                        vec![
                            (parent.span, "value".to_string()),
                            (span.shrink_to_lo(), format!("let mut value = {value};{indent}")),
                        ],
                        Applicability::MaybeIncorrect,
                    );
                }
            }
        }
        can_suggest_clone
    }

    /// We have `S { foo: val, ..base }`, and we suggest instead writing
    /// `S { foo: val, bar: base.bar.clone(), .. }` when valid.
    fn suggest_cloning_on_functional_record_update(
        &self,
        err: &mut Diag<'_>,
        ty: Ty<'tcx>,
        expr: &'cx hir::Expr<'cx>,
    ) {
        let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
        let hir::ExprKind::Struct(struct_qpath, fields, Some(base)) = expr.kind else { return };
        let hir::QPath::Resolved(_, path) = struct_qpath else { return };
        let hir::def::Res::Def(_, def_id) = path.res else { return };
        let Some(expr_ty) = typeck_results.node_type_opt(expr.hir_id) else { return };
        let ty::Adt(def, args) = expr_ty.kind() else { return };
        let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = base.kind else { return };
        let (hir::def::Res::Local(_)
        | hir::def::Res::Def(
            DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } | DefKind::AssocConst,
            _,
        )) = path.res
        else {
            return;
        };
        let Ok(base_str) = self.infcx.tcx.sess.source_map().span_to_snippet(base.span) else {
            return;
        };

        // 1. look for the fields of type `ty`.
        // 2. check if they are clone and add them to suggestion
        // 3. check if there are any values left to `..` and remove it if not
        // 4. emit suggestion to clone the field directly as `bar: base.bar.clone()`

        let mut final_field_count = fields.len();
        let Some(variant) = def.variants().iter().find(|variant| variant.def_id == def_id) else {
            // When we have an enum, look for the variant that corresponds to the variant the user
            // wrote.
            return;
        };
        let mut sugg = vec![];
        for field in &variant.fields {
            // In practice unless there are more than one field with the same type, we'll be
            // suggesting a single field at a type, because we don't aggregate multiple borrow
            // checker errors involving the functional record update sytnax into a single one.
            let field_ty = field.ty(self.infcx.tcx, args);
            let ident = field.ident(self.infcx.tcx);
            if field_ty == ty && fields.iter().all(|field| field.ident.name != ident.name) {
                // Suggest adding field and cloning it.
                sugg.push(format!("{ident}: {base_str}.{ident}.clone()"));
                final_field_count += 1;
            }
        }
        let (span, sugg) = match fields {
            [.., last] => (
                if final_field_count == variant.fields.len() {
                    // We'll remove the `..base` as there aren't any fields left.
                    last.span.shrink_to_hi().with_hi(base.span.hi())
                } else {
                    last.span.shrink_to_hi()
                },
                format!(", {}", sugg.join(", ")),
            ),
            // Account for no fields in suggestion span.
            [] => (
                expr.span.with_lo(struct_qpath.span().hi()),
                if final_field_count == variant.fields.len() {
                    // We'll remove the `..base` as there aren't any fields left.
                    format!(" {{ {} }}", sugg.join(", "))
                } else {
                    format!(" {{ {}, ..{base_str} }}", sugg.join(", "))
                },
            ),
        };
        let prefix = if !self.implements_clone(ty) {
            let msg = format!("`{ty}` doesn't implement `Copy` or `Clone`");
            if let ty::Adt(def, _) = ty.kind() {
                err.span_note(self.infcx.tcx.def_span(def.did()), msg);
            } else {
                err.note(msg);
            }
            format!("if `{ty}` implemented `Clone`, you could ")
        } else {
            String::new()
        };
        let msg = format!(
            "{prefix}clone the value from the field instead of using the functional record update \
             syntax",
        );
        err.span_suggestion_verbose(span, msg, sugg, Applicability::MachineApplicable);
    }

    pub(crate) fn suggest_cloning(
        &self,
        err: &mut Diag<'_>,
        ty: Ty<'tcx>,
        mut expr: &'cx hir::Expr<'cx>,
        mut other_expr: Option<&'cx hir::Expr<'cx>>,
        use_spans: Option<UseSpans<'tcx>>,
    ) {
        if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
            // We have `S { foo: val, ..base }`. In `check_aggregate_rvalue` we have a single
            // `Location` that covers both the `S { ... }` literal, all of its fields and the
            // `base`. If the move happens because of `S { foo: val, bar: base.bar }` the `expr`
            //  will already be correct. Instead, we see if we can suggest writing.
            self.suggest_cloning_on_functional_record_update(err, ty, expr);
            return;
        }

        if let Some(some_other_expr) = other_expr
            && let Some(parent_binop) =
                self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
                    if let (hir_id, hir::Node::Expr(e)) = n
                        && let hir::ExprKind::AssignOp(_binop, target, _arg) = e.kind
                        && target.hir_id == expr.hir_id
                    {
                        Some(hir_id)
                    } else {
                        None
                    }
                })
            && let Some(other_parent_binop) =
                self.infcx.tcx.hir().parent_iter(some_other_expr.hir_id).find_map(|n| {
                    if let (hir_id, hir::Node::Expr(expr)) = n
                        && let hir::ExprKind::AssignOp(..) = expr.kind
                    {
                        Some(hir_id)
                    } else {
                        None
                    }
                })
            && parent_binop == other_parent_binop
        {
            // Explicitly look for `expr += other_expr;` and avoid suggesting
            // `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
            other_expr = Some(expr);
            expr = some_other_expr;
        }
        'outer: {
            if let ty::Ref(..) = ty.kind() {
                // We check for either `let binding = foo(expr, other_expr);` or
                // `foo(expr, other_expr);` and if so we don't suggest an incorrect
                // `foo(expr, other_expr).clone()`
                if let Some(other_expr) = other_expr
                    && let Some(parent_let) =
                        self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
                            if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
                                Some(hir_id)
                            } else {
                                None
                            }
                        })
                    && let Some(other_parent_let) =
                        self.infcx.tcx.hir().parent_iter(other_expr.hir_id).find_map(|n| {
                            if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
                                Some(hir_id)
                            } else {
                                None
                            }
                        })
                    && parent_let == other_parent_let
                {
                    // Explicitly check that we don't have `foo(&*expr, other_expr)`, as cloning the
                    // result of `foo(...)` won't help.
                    break 'outer;
                }

                // We're suggesting `.clone()` on an borrowed value. See if the expression we have
                // is an argument to a function or method call, and try to suggest cloning the
                // *result* of the call, instead of the argument. This is closest to what people
                // would actually be looking for in most cases, with maybe the exception of things
                // like `fn(T) -> T`, but even then it is reasonable.
                let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
                let mut prev = expr;
                while let hir::Node::Expr(parent) = self.infcx.tcx.parent_hir_node(prev.hir_id) {
                    if let hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) = parent.kind
                        && let Some(call_ty) = typeck_results.node_type_opt(parent.hir_id)
                        && let call_ty = call_ty.peel_refs()
                        && (!call_ty
                            .walk()
                            .any(|t| matches!(t.unpack(), ty::GenericArgKind::Lifetime(_)))
                            || if let ty::Alias(ty::Projection, _) = call_ty.kind() {
                                // FIXME: this isn't quite right with lifetimes on assoc types,
                                // but ignore for now. We will only suggest cloning if
                                // `<Ty as Trait>::Assoc: Clone`, which should keep false positives
                                // down to a managable ammount.
                                true
                            } else {
                                false
                            })
                        && self.implements_clone(call_ty)
                        && self.suggest_cloning_inner(err, call_ty, parent)
                    {
                        return;
                    }
                    prev = parent;
                }
            }
        }
        let ty = ty.peel_refs();
        if self.implements_clone(ty) {
            self.suggest_cloning_inner(err, ty, expr);
        } else if let ty::Adt(def, args) = ty.kind()
            && def.did().as_local().is_some()
            && def.variants().iter().all(|variant| {
                variant
                    .fields
                    .iter()
                    .all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
            })
        {
            let ty_span = self.infcx.tcx.def_span(def.did());
            let mut span: MultiSpan = ty_span.into();
            span.push_span_label(ty_span, "consider implementing `Clone` for this type");
            span.push_span_label(expr.span, "you could clone this value");
            err.span_note(
                span,
                format!("if `{ty}` implemented `Clone`, you could clone the value"),
            );
        } else if let ty::Param(param) = ty.kind()
            && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait()
            && let generics = self.infcx.tcx.generics_of(self.mir_def_id())
            && let generic_param = generics.type_param(*param, self.infcx.tcx)
            && let param_span = self.infcx.tcx.def_span(generic_param.def_id)
            && if let Some(UseSpans::FnSelfUse { kind, .. }) = use_spans
                && let CallKind::FnCall { fn_trait_id, self_ty } = kind
                && let ty::Param(_) = self_ty.kind()
                && ty == self_ty
                && [
                    self.infcx.tcx.lang_items().fn_once_trait(),
                    self.infcx.tcx.lang_items().fn_mut_trait(),
                    self.infcx.tcx.lang_items().fn_trait(),
                ]
                .contains(&Some(fn_trait_id))
            {
                // Do not suggest `F: FnOnce() + Clone`.
                false
            } else {
                true
            }
        {
            let mut span: MultiSpan = param_span.into();
            span.push_span_label(
                param_span,
                "consider constraining this type parameter with `Clone`",
            );
            span.push_span_label(expr.span, "you could clone this value");
            err.span_help(
                span,
                format!("if `{ty}` implemented `Clone`, you could clone the value"),
            );
        }
    }

    pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool {
        let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false };
        self.infcx
            .type_implements_trait(clone_trait_def, [ty], self.param_env)
            .must_apply_modulo_regions()
    }

    /// Given an expression, check if it is a method call `foo.clone()`, where `foo` and
    /// `foo.clone()` both have the same type, returning the span for `.clone()` if so.
    pub(crate) fn clone_on_reference(&self, expr: &hir::Expr<'_>) -> Option<Span> {
        let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
        if let hir::ExprKind::MethodCall(segment, rcvr, args, span) = expr.kind
            && let Some(expr_ty) = typeck_results.node_type_opt(expr.hir_id)
            && let Some(rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id)
            && rcvr_ty == expr_ty
            && segment.ident.name == sym::clone
            && args.is_empty()
        {
            Some(span)
        } else {
            None
        }
    }

    fn in_move_closure(&self, expr: &hir::Expr<'_>) -> bool {
        for (_, node) in self.infcx.tcx.hir().parent_iter(expr.hir_id) {
            if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) = node
                && let hir::CaptureBy::Value { .. } = closure.capture_clause
            {
                // `move || x.clone()` will not work. FIXME: suggest `let y = x.clone(); move || y`
                return true;
            }
        }
        false
    }

    fn suggest_cloning_inner(
        &self,
        err: &mut Diag<'_>,
        ty: Ty<'tcx>,
        expr: &hir::Expr<'_>,
    ) -> bool {
        let tcx = self.infcx.tcx;
        if let Some(_) = self.clone_on_reference(expr) {
            // Avoid redundant clone suggestion already suggested in `explain_captures`.
            // See `tests/ui/moves/needs-clone-through-deref.rs`
            return false;
        }
        if self.in_move_closure(expr) {
            return false;
        }
        // Try to find predicates on *generic params* that would allow copying `ty`
        let suggestion =
            if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
                format!(": {symbol}.clone()")
            } else {
                ".clone()".to_owned()
            };
        let mut sugg = Vec::with_capacity(2);
        let mut inner_expr = expr;
        // Remove uses of `&` and `*` when suggesting `.clone()`.
        while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
            &inner_expr.kind
        {
            if let hir::ExprKind::AddrOf(_, hir::Mutability::Mut, _) = inner_expr.kind {
                // We assume that `&mut` refs are desired for their side-effects, so cloning the
                // value wouldn't do what the user wanted.
                return false;
            }
            inner_expr = inner;
        }
        if inner_expr.span.lo() != expr.span.lo() {
            sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
        }
        let span = if inner_expr.span.hi() != expr.span.hi() {
            // Account for `(*x)` to suggest `x.clone()`.
            expr.span.with_lo(inner_expr.span.hi())
        } else {
            expr.span.shrink_to_hi()
        };
        sugg.push((span, suggestion));
        let msg = if let ty::Adt(def, _) = ty.kind()
            && [tcx.get_diagnostic_item(sym::Arc), tcx.get_diagnostic_item(sym::Rc)]
                .contains(&Some(def.did()))
        {
            "clone the value to increment its reference count"
        } else {
            "consider cloning the value if the performance cost is acceptable"
        };
        err.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
        true
    }

    fn suggest_adding_bounds(&self, err: &mut Diag<'_>, ty: Ty<'tcx>, def_id: DefId, span: Span) {
        let tcx = self.infcx.tcx;
        let generics = tcx.generics_of(self.mir_def_id());

        let Some(hir_generics) = tcx
            .typeck_root_def_id(self.mir_def_id().to_def_id())
            .as_local()
            .and_then(|def_id| tcx.hir().get_generics(def_id))
        else {
            return;
        };
        // Try to find predicates on *generic params* that would allow copying `ty`
        let ocx = ObligationCtxt::new(self.infcx);
        let cause = ObligationCause::misc(span, self.mir_def_id());

        ocx.register_bound(cause, self.param_env, ty, def_id);
        let errors = ocx.select_all_or_error();

        // Only emit suggestion if all required predicates are on generic
        let predicates: Result<Vec<_>, _> = errors
            .into_iter()
            .map(|err| match err.obligation.predicate.kind().skip_binder() {
                PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
                    match *predicate.self_ty().kind() {
                        ty::Param(param_ty) => Ok((
                            generics.type_param(param_ty, tcx),
                            predicate.trait_ref.print_only_trait_path().to_string(),
                        )),
                        _ => Err(()),
                    }
                }
                _ => Err(()),
            })
            .collect();

        if let Ok(predicates) = predicates {
            suggest_constraining_type_params(
                tcx,
                hir_generics,
                err,
                predicates
                    .iter()
                    .map(|(param, constraint)| (param.name.as_str(), &**constraint, None)),
                None,
            );
        }
    }

    pub(crate) fn report_move_out_while_borrowed(
        &mut self,
        location: Location,
        (place, span): (Place<'tcx>, Span),
        borrow: &BorrowData<'tcx>,
    ) {
        debug!(
            "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}",
            location, place, span, borrow
        );
        let value_msg = self.describe_any_place(place.as_ref());
        let borrow_msg = self.describe_any_place(borrow.borrowed_place.as_ref());

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.args_or_use();

        let move_spans = self.move_spans(place.as_ref(), location);
        let span = move_spans.args_or_use();

        let mut err = self.cannot_move_when_borrowed(
            span,
            borrow_span,
            &self.describe_any_place(place.as_ref()),
            &borrow_msg,
            &value_msg,
        );

        borrow_spans.var_path_only_subdiag(
            self.dcx(),
            &mut err,
            crate::InitializationRequiringAction::Borrow,
        );

        move_spans.var_subdiag(self.dcx(), &mut err, None, |kind, var_span| {
            use crate::session_diagnostics::CaptureVarCause::*;
            match kind {
                hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span },
                hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                    MoveUseInClosure { var_span }
                }
            }
        });

        self.explain_why_borrow_contains_point(location, borrow, None)
            .add_explanation_to_diagnostic(
                self.infcx.tcx,
                self.body,
                &self.local_names,
                &mut err,
                "",
                Some(borrow_span),
                None,
            );
        self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
        let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
        if let Some(expr) = self.find_expr(borrow_span)
            && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
        {
            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
        }
        self.buffer_error(err);
    }

    pub(crate) fn report_use_while_mutably_borrowed(
        &self,
        location: Location,
        (place, _span): (Place<'tcx>, Span),
        borrow: &BorrowData<'tcx>,
    ) -> Diag<'tcx> {
        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.args_or_use();

        // Conflicting borrows are reported separately, so only check for move
        // captures.
        let use_spans = self.move_spans(place.as_ref(), location);
        let span = use_spans.var_or_use();

        // If the attempted use is in a closure then we do not care about the path span of the place we are currently trying to use
        // we call `var_span_label` on `borrow_spans` to annotate if the existing borrow was in a closure
        let mut err = self.cannot_use_when_mutably_borrowed(
            span,
            &self.describe_any_place(place.as_ref()),
            borrow_span,
            &self.describe_any_place(borrow.borrowed_place.as_ref()),
        );
        borrow_spans.var_subdiag(self.dcx(), &mut err, Some(borrow.kind), |kind, var_span| {
            use crate::session_diagnostics::CaptureVarCause::*;
            let place = &borrow.borrowed_place;
            let desc_place = self.describe_any_place(place.as_ref());
            match kind {
                hir::ClosureKind::Coroutine(_) => {
                    BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true }
                }
                hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                    BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }
                }
            }
        });

        self.explain_why_borrow_contains_point(location, borrow, None)
            .add_explanation_to_diagnostic(
                self.infcx.tcx,
                self.body,
                &self.local_names,
                &mut err,
                "",
                None,
                None,
            );
        err
    }

    pub(crate) fn report_conflicting_borrow(
        &self,
        location: Location,
        (place, span): (Place<'tcx>, Span),
        gen_borrow_kind: BorrowKind,
        issued_borrow: &BorrowData<'tcx>,
    ) -> Diag<'tcx> {
        let issued_spans = self.retrieve_borrow_spans(issued_borrow);
        let issued_span = issued_spans.args_or_use();

        let borrow_spans = self.borrow_spans(span, location);
        let span = borrow_spans.args_or_use();

        let container_name = if issued_spans.for_coroutine() || borrow_spans.for_coroutine() {
            "coroutine"
        } else {
            "closure"
        };

        let (desc_place, msg_place, msg_borrow, union_type_name) =
            self.describe_place_for_conflicting_borrow(place, issued_borrow.borrowed_place);

        let explanation = self.explain_why_borrow_contains_point(location, issued_borrow, None);
        let second_borrow_desc = if explanation.is_explained() { "second " } else { "" };

        // FIXME: supply non-"" `opt_via` when appropriate
        let first_borrow_desc;
        let mut err = match (gen_borrow_kind, issued_borrow.kind) {
            (
                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
                BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
            ) => {
                first_borrow_desc = "mutable ";
                let mut err = self.cannot_reborrow_already_borrowed(
                    span,
                    &desc_place,
                    &msg_place,
                    "immutable",
                    issued_span,
                    "it",
                    "mutable",
                    &msg_borrow,
                    None,
                );
                self.suggest_slice_method_if_applicable(
                    &mut err,
                    place,
                    issued_borrow.borrowed_place,
                    span,
                    issued_span,
                );
                err
            }
            (
                BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
            ) => {
                first_borrow_desc = "immutable ";
                let mut err = self.cannot_reborrow_already_borrowed(
                    span,
                    &desc_place,
                    &msg_place,
                    "mutable",
                    issued_span,
                    "it",
                    "immutable",
                    &msg_borrow,
                    None,
                );
                self.suggest_slice_method_if_applicable(
                    &mut err,
                    place,
                    issued_borrow.borrowed_place,
                    span,
                    issued_span,
                );
                self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
                self.suggest_using_closure_argument_instead_of_capture(
                    &mut err,
                    issued_borrow.borrowed_place,
                    &issued_spans,
                );
                err
            }

            (
                BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
                BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
            ) => {
                first_borrow_desc = "first ";
                let mut err = self.cannot_mutably_borrow_multiply(
                    span,
                    &desc_place,
                    &msg_place,
                    issued_span,
                    &msg_borrow,
                    None,
                );
                self.suggest_slice_method_if_applicable(
                    &mut err,
                    place,
                    issued_borrow.borrowed_place,
                    span,
                    issued_span,
                );
                self.suggest_using_closure_argument_instead_of_capture(
                    &mut err,
                    issued_borrow.borrowed_place,
                    &issued_spans,
                );
                self.explain_iterator_advancement_in_for_loop_if_applicable(
                    &mut err,
                    span,
                    &issued_spans,
                );
                err
            }

            (
                BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
                BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
            ) => {
                first_borrow_desc = "first ";
                self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
            }

            (BorrowKind::Mut { .. }, BorrowKind::Fake(FakeBorrowKind::Shallow)) => {
                if let Some(immutable_section_description) =
                    self.classify_immutable_section(issued_borrow.assigned_place)
                {
                    let mut err = self.cannot_mutate_in_immutable_section(
                        span,
                        issued_span,
                        &desc_place,
                        immutable_section_description,
                        "mutably borrow",
                    );
                    borrow_spans.var_subdiag(
                        self.dcx(),
                        &mut err,
                        Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
                        |kind, var_span| {
                            use crate::session_diagnostics::CaptureVarCause::*;
                            match kind {
                                hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
                                    place: desc_place,
                                    var_span,
                                    is_single_var: true,
                                },
                                hir::ClosureKind::Closure
                                | hir::ClosureKind::CoroutineClosure(_) => BorrowUsePlaceClosure {
                                    place: desc_place,
                                    var_span,
                                    is_single_var: true,
                                },
                            }
                        },
                    );
                    return err;
                } else {
                    first_borrow_desc = "immutable ";
                    self.cannot_reborrow_already_borrowed(
                        span,
                        &desc_place,
                        &msg_place,
                        "mutable",
                        issued_span,
                        "it",
                        "immutable",
                        &msg_borrow,
                        None,
                    )
                }
            }

            (BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }, _) => {
                first_borrow_desc = "first ";
                self.cannot_uniquely_borrow_by_one_closure(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    issued_span,
                    "it",
                    "",
                    None,
                )
            }

            (
                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
                BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
            ) => {
                first_borrow_desc = "first ";
                self.cannot_reborrow_already_uniquely_borrowed(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    "immutable",
                    issued_span,
                    "",
                    None,
                    second_borrow_desc,
                )
            }

            (BorrowKind::Mut { .. }, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
                first_borrow_desc = "first ";
                self.cannot_reborrow_already_uniquely_borrowed(
                    span,
                    container_name,
                    &desc_place,
                    "",
                    "mutable",
                    issued_span,
                    "",
                    None,
                    second_borrow_desc,
                )
            }

            (
                BorrowKind::Shared | BorrowKind::Fake(FakeBorrowKind::Deep),
                BorrowKind::Shared | BorrowKind::Fake(_),
            )
            | (
                BorrowKind::Fake(FakeBorrowKind::Shallow),
                BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Fake(_),
            ) => {
                unreachable!()
            }
        };

        if issued_spans == borrow_spans {
            borrow_spans.var_subdiag(
                self.dcx(),
                &mut err,
                Some(gen_borrow_kind),
                |kind, var_span| {
                    use crate::session_diagnostics::CaptureVarCause::*;
                    match kind {
                        hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
                            place: desc_place,
                            var_span,
                            is_single_var: false,
                        },
                        hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                            BorrowUsePlaceClosure {
                                place: desc_place,
                                var_span,
                                is_single_var: false,
                            }
                        }
                    }
                },
            );
        } else {
            issued_spans.var_subdiag(
                self.dcx(),
                &mut err,
                Some(issued_borrow.kind),
                |kind, var_span| {
                    use crate::session_diagnostics::CaptureVarCause::*;
                    let borrow_place = &issued_borrow.borrowed_place;
                    let borrow_place_desc = self.describe_any_place(borrow_place.as_ref());
                    match kind {
                        hir::ClosureKind::Coroutine(_) => {
                            FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span }
                        }
                        hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                            FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }
                        }
                    }
                },
            );

            borrow_spans.var_subdiag(
                self.dcx(),
                &mut err,
                Some(gen_borrow_kind),
                |kind, var_span| {
                    use crate::session_diagnostics::CaptureVarCause::*;
                    match kind {
                        hir::ClosureKind::Coroutine(_) => {
                            SecondBorrowUsePlaceCoroutine { place: desc_place, var_span }
                        }
                        hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                            SecondBorrowUsePlaceClosure { place: desc_place, var_span }
                        }
                    }
                },
            );
        }

        if union_type_name != "" {
            err.note(format!(
                "{msg_place} is a field of the union `{union_type_name}`, so it overlaps the field {msg_borrow}",
            ));
        }

        explanation.add_explanation_to_diagnostic(
            self.infcx.tcx,
            self.body,
            &self.local_names,
            &mut err,
            first_borrow_desc,
            None,
            Some((issued_span, span)),
        );

        self.suggest_using_local_if_applicable(&mut err, location, issued_borrow, explanation);
        self.suggest_copy_for_type_in_cloned_ref(&mut err, place);

        err
    }

    fn suggest_copy_for_type_in_cloned_ref(&self, err: &mut Diag<'tcx>, place: Place<'tcx>) {
        let tcx = self.infcx.tcx;
        let hir = tcx.hir();
        let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };

        struct FindUselessClone<'tcx> {
            tcx: TyCtxt<'tcx>,
            typeck_results: &'tcx ty::TypeckResults<'tcx>,
            pub clones: Vec<&'tcx hir::Expr<'tcx>>,
        }
        impl<'tcx> FindUselessClone<'tcx> {
            pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
                Self { tcx, typeck_results: tcx.typeck(def_id), clones: vec![] }
            }
        }
        impl<'tcx> Visitor<'tcx> for FindUselessClone<'tcx> {
            fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
                if let hir::ExprKind::MethodCall(..) = ex.kind
                    && let Some(method_def_id) =
                        self.typeck_results.type_dependent_def_id(ex.hir_id)
                    && self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
                {
                    self.clones.push(ex);
                }
                hir::intravisit::walk_expr(self, ex);
            }
        }

        let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id());

        let body = hir.body(body_id).value;
        expr_finder.visit_expr(body);

        pub struct Holds<'tcx> {
            ty: Ty<'tcx>,
            holds: bool,
        }

        impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Holds<'tcx> {
            type Result = std::ops::ControlFlow<()>;

            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                if t == self.ty {
                    self.holds = true;
                }
                t.super_visit_with(self)
            }
        }

        let mut types_to_constrain = FxIndexSet::default();

        let local_ty = self.body.local_decls[place.local].ty;
        let typeck_results = tcx.typeck(self.mir_def_id());
        let clone = tcx.require_lang_item(LangItem::Clone, Some(body.span));
        for expr in expr_finder.clones {
            if let hir::ExprKind::MethodCall(_, rcvr, _, span) = expr.kind
                && let Some(rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id)
                && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
                && rcvr_ty == ty
                && let ty::Ref(_, inner, _) = rcvr_ty.kind()
                && let inner = inner.peel_refs()
                && let mut v = (Holds { ty: inner, holds: false })
                && let _ = v.visit_ty(local_ty)
                && v.holds
                && let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
            {
                err.span_label(
                    span,
                    format!(
                        "this call doesn't do anything, the result is still `{rcvr_ty}` \
                             because `{inner}` doesn't implement `Clone`",
                    ),
                );
                types_to_constrain.insert(inner);
            }
        }
        for ty in types_to_constrain {
            self.suggest_adding_bounds_or_derive(err, ty, clone, body.span);
        }
    }

    pub(crate) fn suggest_adding_bounds_or_derive(
        &self,
        err: &mut Diag<'_>,
        ty: Ty<'tcx>,
        trait_def_id: DefId,
        span: Span,
    ) {
        self.suggest_adding_bounds(err, ty, trait_def_id, span);
        if let ty::Adt(..) = ty.kind() {
            // The type doesn't implement the trait.
            let trait_ref =
                ty::Binder::dummy(ty::TraitRef::new(self.infcx.tcx, trait_def_id, [ty]));
            let obligation = Obligation::new(
                self.infcx.tcx,
                ObligationCause::dummy(),
                self.param_env,
                trait_ref,
            );
            self.infcx.err_ctxt().suggest_derive(
                &obligation,
                err,
                trait_ref.to_predicate(self.infcx.tcx),
            );
        }
    }

    #[instrument(level = "debug", skip(self, err))]
    fn suggest_using_local_if_applicable(
        &self,
        err: &mut Diag<'_>,
        location: Location,
        issued_borrow: &BorrowData<'tcx>,
        explanation: BorrowExplanation<'tcx>,
    ) {
        let used_in_call = matches!(
            explanation,
            BorrowExplanation::UsedLater(LaterUseKind::Call | LaterUseKind::Other, _call_span, _)
        );
        if !used_in_call {
            debug!("not later used in call");
            return;
        }

        let use_span =
            if let BorrowExplanation::UsedLater(LaterUseKind::Other, use_span, _) = explanation {
                Some(use_span)
            } else {
                None
            };

        let outer_call_loc =
            if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location {
                loc
            } else {
                issued_borrow.reserve_location
            };
        let outer_call_stmt = self.body.stmt_at(outer_call_loc);

        let inner_param_location = location;
        let Some(inner_param_stmt) = self.body.stmt_at(inner_param_location).left() else {
            debug!("`inner_param_location` {:?} is not for a statement", inner_param_location);
            return;
        };
        let Some(&inner_param) = inner_param_stmt.kind.as_assign().map(|(p, _)| p) else {
            debug!(
                "`inner_param_location` {:?} is not for an assignment: {:?}",
                inner_param_location, inner_param_stmt
            );
            return;
        };
        let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local);
        let Some((inner_call_loc, inner_call_term)) =
            inner_param_uses.into_iter().find_map(|loc| {
                let Either::Right(term) = self.body.stmt_at(loc) else {
                    debug!("{:?} is a statement, so it can't be a call", loc);
                    return None;
                };
                let TerminatorKind::Call { args, .. } = &term.kind else {
                    debug!("not a call: {:?}", term);
                    return None;
                };
                debug!("checking call args for uses of inner_param: {:?}", args);
                args.iter()
                    .map(|a| &a.node)
                    .any(|a| a == &Operand::Move(inner_param))
                    .then_some((loc, term))
            })
        else {
            debug!("no uses of inner_param found as a by-move call arg");
            return;
        };
        debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc);

        let inner_call_span = inner_call_term.source_info.span;
        let outer_call_span = match use_span {
            Some(span) => span,
            None => outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span,
        };
        if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) {
            // FIXME: This stops the suggestion in some cases where it should be emitted.
            //        Fix the spans for those cases so it's emitted correctly.
            debug!(
                "outer span {:?} does not strictly contain inner span {:?}",
                outer_call_span, inner_call_span
            );
            return;
        }
        err.span_help(
            inner_call_span,
            format!(
                "try adding a local storing this{}...",
                if use_span.is_some() { "" } else { " argument" }
            ),
        );
        err.span_help(
            outer_call_span,
            format!(
                "...and then using that local {}",
                if use_span.is_some() { "here" } else { "as the argument to this call" }
            ),
        );
    }

    pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> {
        let tcx = self.infcx.tcx;
        let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?;
        let mut expr_finder = FindExprBySpan::new(span, tcx);
        expr_finder.visit_expr(tcx.hir().body(body_id).value);
        expr_finder.result
    }

    fn suggest_slice_method_if_applicable(
        &self,
        err: &mut Diag<'_>,
        place: Place<'tcx>,
        borrowed_place: Place<'tcx>,
        span: Span,
        issued_span: Span,
    ) {
        let tcx = self.infcx.tcx;
        let hir = tcx.hir();

        let has_split_at_mut = |ty: Ty<'tcx>| {
            let ty = ty.peel_refs();
            match ty.kind() {
                ty::Array(..) | ty::Slice(..) => true,
                ty::Adt(def, _) if tcx.get_diagnostic_item(sym::Vec) == Some(def.did()) => true,
                _ if ty == tcx.types.str_ => true,
                _ => false,
            }
        };
        if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)])
        | (
            [ProjectionElem::Deref, ProjectionElem::Index(index1)],
            [ProjectionElem::Deref, ProjectionElem::Index(index2)],
        ) = (&place.projection[..], &borrowed_place.projection[..])
        {
            let decl1 = &self.body.local_decls[*index1];
            let decl2 = &self.body.local_decls[*index2];

            let mut note_default_suggestion = || {
                err.help(
                    "consider using `.split_at_mut(position)` or similar method to obtain two \
                     mutable non-overlapping sub-slices",
                )
                .help(
                    "consider using `.swap(index_1, index_2)` to swap elements at the specified \
                     indices",
                );
            };

            let Some(index1) = self.find_expr(decl1.source_info.span) else {
                note_default_suggestion();
                return;
            };

            let Some(index2) = self.find_expr(decl2.source_info.span) else {
                note_default_suggestion();
                return;
            };

            let sm = tcx.sess.source_map();

            let Ok(index1_str) = sm.span_to_snippet(index1.span) else {
                note_default_suggestion();
                return;
            };

            let Ok(index2_str) = sm.span_to_snippet(index2.span) else {
                note_default_suggestion();
                return;
            };

            let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
                if let hir::Node::Expr(expr) = tcx.hir_node(id)
                    && let hir::ExprKind::Index(obj, ..) = expr.kind
                {
                    Some(obj)
                } else {
                    None
                }
            }) else {
                note_default_suggestion();
                return;
            };

            let Ok(obj_str) = sm.span_to_snippet(object.span) else {
                note_default_suggestion();
                return;
            };

            let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
                if let hir::Node::Expr(call) = tcx.hir_node(id)
                    && let hir::ExprKind::Call(callee, ..) = call.kind
                    && let hir::ExprKind::Path(qpath) = callee.kind
                    && let hir::QPath::Resolved(None, res) = qpath
                    && let hir::def::Res::Def(_, did) = res.res
                    && tcx.is_diagnostic_item(sym::mem_swap, did)
                {
                    Some(call)
                } else {
                    None
                }
            }) else {
                let hir::Node::Expr(parent) = tcx.parent_hir_node(index1.hir_id) else { return };
                let hir::ExprKind::Index(_, idx1, _) = parent.kind else { return };
                let hir::Node::Expr(parent) = tcx.parent_hir_node(index2.hir_id) else { return };
                let hir::ExprKind::Index(_, idx2, _) = parent.kind else { return };
                if !idx1.equivalent_for_indexing(idx2) {
                    err.help("use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices");
                }
                return;
            };

            err.span_suggestion(
                swap_call.span,
                "use `.swap()` to swap elements at the specified indices instead",
                format!("{obj_str}.swap({index1_str}, {index2_str})"),
                Applicability::MachineApplicable,
            );
            return;
        }
        let place_ty = PlaceRef::ty(&place.as_ref(), self.body, tcx).ty;
        let borrowed_place_ty = PlaceRef::ty(&borrowed_place.as_ref(), self.body, tcx).ty;
        if !has_split_at_mut(place_ty) && !has_split_at_mut(borrowed_place_ty) {
            // Only mention `split_at_mut` on `Vec`, array and slices.
            return;
        }
        let Some(index1) = self.find_expr(span) else { return };
        let hir::Node::Expr(parent) = tcx.parent_hir_node(index1.hir_id) else { return };
        let hir::ExprKind::Index(_, idx1, _) = parent.kind else { return };
        let Some(index2) = self.find_expr(issued_span) else { return };
        let hir::Node::Expr(parent) = tcx.parent_hir_node(index2.hir_id) else { return };
        let hir::ExprKind::Index(_, idx2, _) = parent.kind else { return };
        if idx1.equivalent_for_indexing(idx2) {
            // `let a = &mut foo[0]` and `let b = &mut foo[0]`? Don't mention `split_at_mut`
            return;
        }
        err.help("use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices");
    }

    /// Suggest using `while let` for call `next` on an iterator in a for loop.
    ///
    /// For example:
    /// ```ignore (illustrative)
    ///
    /// for x in iter {
    ///     ...
    ///     iter.next()
    /// }
    /// ```
    pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
        &self,
        err: &mut Diag<'_>,
        span: Span,
        issued_spans: &UseSpans<'tcx>,
    ) {
        let issue_span = issued_spans.args_or_use();
        let tcx = self.infcx.tcx;
        let hir = tcx.hir();

        let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
        let typeck_results = tcx.typeck(self.mir_def_id());

        struct ExprFinder<'hir> {
            issue_span: Span,
            expr_span: Span,
            body_expr: Option<&'hir hir::Expr<'hir>>,
            loop_bind: Option<&'hir Ident>,
            loop_span: Option<Span>,
            head_span: Option<Span>,
            pat_span: Option<Span>,
            head: Option<&'hir hir::Expr<'hir>>,
        }
        impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
            fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
                // Try to find
                // let result = match IntoIterator::into_iter(<head>) {
                //     mut iter => {
                //         [opt_ident]: loop {
                //             match Iterator::next(&mut iter) {
                //                 None => break,
                //                 Some(<pat>) => <body>,
                //             };
                //         }
                //     }
                // };
                // corresponding to the desugaring of a for loop `for <pat> in <head> { <body> }`.
                if let hir::ExprKind::Call(path, [arg]) = ex.kind
                    && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
                        path.kind
                    && arg.span.contains(self.issue_span)
                {
                    // Find `IntoIterator::into_iter(<head>)`
                    self.head = Some(arg);
                }
                if let hir::ExprKind::Loop(
                    hir::Block { stmts: [stmt, ..], .. },
                    _,
                    hir::LoopSource::ForLoop,
                    _,
                ) = ex.kind
                    && let hir::StmtKind::Expr(hir::Expr {
                        kind: hir::ExprKind::Match(call, [_, bind, ..], _),
                        span: head_span,
                        ..
                    }) = stmt.kind
                    && let hir::ExprKind::Call(path, _args) = call.kind
                    && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _)) =
                        path.kind
                    && let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind
                    && let hir::QPath::LangItem(LangItem::OptionSome, pat_span) = path
                    && call.span.contains(self.issue_span)
                {
                    // Find `<pat>` and the span for the whole `for` loop.
                    if let PatField {
                        pat: hir::Pat { kind: hir::PatKind::Binding(_, _, ident, ..), .. },
                        ..
                    } = field
                    {
                        self.loop_bind = Some(ident);
                    }
                    self.head_span = Some(*head_span);
                    self.pat_span = Some(pat_span);
                    self.loop_span = Some(stmt.span);
                }

                if let hir::ExprKind::MethodCall(body_call, recv, ..) = ex.kind
                    && body_call.ident.name == sym::next
                    && recv.span.source_equal(self.expr_span)
                {
                    self.body_expr = Some(ex);
                }

                hir::intravisit::walk_expr(self, ex);
            }
        }
        let mut finder = ExprFinder {
            expr_span: span,
            issue_span,
            loop_bind: None,
            body_expr: None,
            head_span: None,
            loop_span: None,
            pat_span: None,
            head: None,
        };
        finder.visit_expr(hir.body(body_id).value);

        if let Some(body_expr) = finder.body_expr
            && let Some(loop_span) = finder.loop_span
            && let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id)
            && let Some(trait_did) = tcx.trait_of_item(def_id)
            && tcx.is_diagnostic_item(sym::Iterator, trait_did)
        {
            if let Some(loop_bind) = finder.loop_bind {
                err.note(format!(
                    "a for loop advances the iterator for you, the result is stored in `{}`",
                    loop_bind.name,
                ));
            } else {
                err.note(
                    "a for loop advances the iterator for you, the result is stored in its pattern",
                );
            }
            let msg = "if you want to call `next` on a iterator within the loop, consider using \
                       `while let`";
            if let Some(head) = finder.head
                && let Some(pat_span) = finder.pat_span
                && loop_span.contains(body_expr.span)
                && loop_span.contains(head.span)
            {
                let sm = self.infcx.tcx.sess.source_map();

                let mut sugg = vec![];
                if let hir::ExprKind::Path(hir::QPath::Resolved(None, _)) = head.kind {
                    // A bare path doesn't need a `let` assignment, it's already a simple
                    // binding access.
                    // As a new binding wasn't added, we don't need to modify the advancing call.
                    sugg.push((loop_span.with_hi(pat_span.lo()), "while let Some(".to_string()));
                    sugg.push((
                        pat_span.shrink_to_hi().with_hi(head.span.lo()),
                        ") = ".to_string(),
                    ));
                    sugg.push((head.span.shrink_to_hi(), ".next()".to_string()));
                } else {
                    // Needs a new a `let` binding.
                    let indent = if let Some(indent) = sm.indentation_before(loop_span) {
                        format!("\n{indent}")
                    } else {
                        " ".to_string()
                    };
                    let Ok(head_str) = sm.span_to_snippet(head.span) else {
                        err.help(msg);
                        return;
                    };
                    sugg.push((
                        loop_span.with_hi(pat_span.lo()),
                        format!("let iter = {head_str};{indent}while let Some("),
                    ));
                    sugg.push((
                        pat_span.shrink_to_hi().with_hi(head.span.hi()),
                        ") = iter.next()".to_string(),
                    ));
                    // As a new binding was added, we should change how the iterator is advanced to
                    // use the newly introduced binding.
                    if let hir::ExprKind::MethodCall(_, recv, ..) = body_expr.kind
                        && let hir::ExprKind::Path(hir::QPath::Resolved(None, ..)) = recv.kind
                    {
                        // As we introduced a `let iter = <head>;`, we need to change where the
                        // already borrowed value was accessed from `<recv>.next()` to
                        // `iter.next()`.
                        sugg.push((recv.span, "iter".to_string()));
                    }
                }
                err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
            } else {
                err.help(msg);
            }
        }
    }

    /// Suggest using closure argument instead of capture.
    ///
    /// For example:
    /// ```ignore (illustrative)
    /// struct S;
    ///
    /// impl S {
    ///     fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ }
    ///     fn x(&self) {}
    /// }
    ///
    ///     let mut v = S;
    ///     v.call(|this: &mut S| v.x());
    /// //  ^\                    ^-- help: try using the closure argument: `this`
    /// //    *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable
    /// ```
    fn suggest_using_closure_argument_instead_of_capture(
        &self,
        err: &mut Diag<'_>,
        borrowed_place: Place<'tcx>,
        issued_spans: &UseSpans<'tcx>,
    ) {
        let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
        let tcx = self.infcx.tcx;
        let hir = tcx.hir();

        // Get the type of the local that we are trying to borrow
        let local = borrowed_place.local;
        let local_ty = self.body.local_decls[local].ty;

        // Get the body the error happens in
        let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };

        let body_expr = hir.body(body_id).value;

        struct ClosureFinder<'hir> {
            hir: rustc_middle::hir::map::Map<'hir>,
            borrow_span: Span,
            res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
            /// The path expression with the `borrow_span` span
            error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>,
        }
        impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
            type NestedFilter = OnlyBodies;

            fn nested_visit_map(&mut self) -> Self::Map {
                self.hir
            }

            fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
                if let hir::ExprKind::Path(qpath) = &ex.kind
                    && ex.span == self.borrow_span
                {
                    self.error_path = Some((ex, qpath));
                }

                if let hir::ExprKind::Closure(closure) = ex.kind
                    && ex.span.contains(self.borrow_span)
                    // To support cases like `|| { v.call(|this| v.get()) }`
                    // FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
                    && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
                {
                    self.res = Some((ex, closure));
                }

                hir::intravisit::walk_expr(self, ex);
            }
        }

        // Find the closure that most tightly wraps `capture_kind_span`
        let mut finder =
            ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
        finder.visit_expr(body_expr);
        let Some((closure_expr, closure)) = finder.res else { return };

        let typeck_results = tcx.typeck(self.mir_def_id());

        // Check that the parent of the closure is a method call,
        // with receiver matching with local's type (modulo refs)
        if let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_expr.hir_id) {
            if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
                let recv_ty = typeck_results.expr_ty(recv);

                if recv_ty.peel_refs() != local_ty {
                    return;
                }
            }
        }

        // Get closure's arguments
        let ty::Closure(_, args) = typeck_results.expr_ty(closure_expr).kind() else {
            /* hir::Closure can be a coroutine too */
            return;
        };
        let sig = args.as_closure().sig();
        let tupled_params = tcx.instantiate_bound_regions_with_erased(
            sig.inputs().iter().next().unwrap().map_bound(|&b| b),
        );
        let ty::Tuple(params) = tupled_params.kind() else { return };

        // Find the first argument with a matching type, get its name
        let Some((_, this_name)) =
            params.iter().zip(hir.body_param_names(closure.body)).find(|(param_ty, name)| {
                // FIXME: also support deref for stuff like `Rc` arguments
                param_ty.peel_refs() == local_ty && name != &Ident::empty()
            })
        else {
            return;
        };

        let spans;
        if let Some((_path_expr, qpath)) = finder.error_path
            && let hir::QPath::Resolved(_, path) = qpath
            && let hir::def::Res::Local(local_id) = path.res
        {
            // Find all references to the problematic variable in this closure body

            struct VariableUseFinder {
                local_id: hir::HirId,
                spans: Vec<Span>,
            }
            impl<'hir> Visitor<'hir> for VariableUseFinder {
                fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
                    if let hir::ExprKind::Path(qpath) = &ex.kind
                        && let hir::QPath::Resolved(_, path) = qpath
                        && let hir::def::Res::Local(local_id) = path.res
                        && local_id == self.local_id
                    {
                        self.spans.push(ex.span);
                    }

                    hir::intravisit::walk_expr(self, ex);
                }
            }

            let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
            finder.visit_expr(hir.body(closure.body).value);

            spans = finder.spans;
        } else {
            spans = vec![capture_kind_span];
        }

        err.multipart_suggestion(
            "try using the closure argument",
            iter::zip(spans, iter::repeat(this_name.to_string())).collect(),
            Applicability::MaybeIncorrect,
        );
    }

    fn suggest_binding_for_closure_capture_self(
        &self,
        err: &mut Diag<'_>,
        issued_spans: &UseSpans<'tcx>,
    ) {
        let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };

        struct ExpressionFinder<'tcx> {
            capture_span: Span,
            closure_change_spans: Vec<Span>,
            closure_arg_span: Option<Span>,
            in_closure: bool,
            suggest_arg: String,
            tcx: TyCtxt<'tcx>,
            closure_local_id: Option<hir::HirId>,
            closure_call_changes: Vec<(Span, String)>,
        }
        impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
            fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
                if e.span.contains(self.capture_span) {
                    if let hir::ExprKind::Closure(&hir::Closure {
                        kind: hir::ClosureKind::Closure,
                        body,
                        fn_arg_span,
                        fn_decl: hir::FnDecl { inputs, .. },
                        ..
                    }) = e.kind
                        && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
                    {
                        self.suggest_arg = "this: &Self".to_string();
                        if inputs.len() > 0 {
                            self.suggest_arg.push_str(", ");
                        }
                        self.in_closure = true;
                        self.closure_arg_span = fn_arg_span;
                        self.visit_expr(body);
                        self.in_closure = false;
                    }
                }
                if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e {
                    if let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
                        && seg.ident.name == kw::SelfLower
                        && self.in_closure
                    {
                        self.closure_change_spans.push(e.span);
                    }
                }
                hir::intravisit::walk_expr(self, e);
            }

            fn visit_local(&mut self, local: &'hir hir::LetStmt<'hir>) {
                if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } =
                    local.pat
                    && let Some(init) = local.init
                {
                    if let hir::Expr {
                        kind:
                            hir::ExprKind::Closure(&hir::Closure {
                                kind: hir::ClosureKind::Closure,
                                ..
                            }),
                        ..
                    } = init
                        && init.span.contains(self.capture_span)
                    {
                        self.closure_local_id = Some(*hir_id);
                    }
                }
                hir::intravisit::walk_local(self, local);
            }

            fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) {
                if let hir::StmtKind::Semi(e) = s.kind
                    && let hir::ExprKind::Call(
                        hir::Expr { kind: hir::ExprKind::Path(path), .. },
                        args,
                    ) = e.kind
                    && let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path
                    && let Res::Local(hir_id) = seg.res
                    && Some(hir_id) == self.closure_local_id
                {
                    let (span, arg_str) = if args.len() > 0 {
                        (args[0].span.shrink_to_lo(), "self, ".to_string())
                    } else {
                        let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span);
                        (span, "(self)".to_string())
                    };
                    self.closure_call_changes.push((span, arg_str));
                }
                hir::intravisit::walk_stmt(self, s);
            }
        }

        if let hir::Node::ImplItem(hir::ImplItem {
            kind: hir::ImplItemKind::Fn(_fn_sig, body_id),
            ..
        }) = self.infcx.tcx.hir_node(self.mir_hir_id())
            && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id)
        {
            let mut finder = ExpressionFinder {
                capture_span: *capture_kind_span,
                closure_change_spans: vec![],
                closure_arg_span: None,
                in_closure: false,
                suggest_arg: String::new(),
                closure_local_id: None,
                closure_call_changes: vec![],
                tcx: self.infcx.tcx,
            };
            finder.visit_expr(expr);

            if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() {
                return;
            }

            let mut sugg = vec![];
            let sm = self.infcx.tcx.sess.source_map();

            if let Some(span) = finder.closure_arg_span {
                sugg.push((sm.next_point(span.shrink_to_lo()).shrink_to_hi(), finder.suggest_arg));
            }
            for span in finder.closure_change_spans {
                sugg.push((span, "this".to_string()));
            }

            for (span, suggest) in finder.closure_call_changes {
                sugg.push((span, suggest));
            }

            err.multipart_suggestion_verbose(
                "try explicitly pass `&Self` into the Closure as an argument",
                sugg,
                Applicability::MachineApplicable,
            );
        }
    }

    /// Returns the description of the root place for a conflicting borrow and the full
    /// descriptions of the places that caused the conflict.
    ///
    /// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is
    /// attempted while a shared borrow is live, then this function will return:
    /// ```
    /// ("x", "", "")
    /// # ;
    /// ```
    /// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while
    /// a shared borrow of another field `x.y`, then this function will return:
    /// ```
    /// ("x", "x.z", "x.y")
    /// # ;
    /// ```
    /// In the more complex union case, where the union is a field of a struct, then if a mutable
    /// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of
    /// another field `x.u.y`, then this function will return:
    /// ```
    /// ("x.u", "x.u.z", "x.u.y")
    /// # ;
    /// ```
    /// This is used when creating error messages like below:
    ///
    /// ```text
    /// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
    /// mutable (via `a.u.s.b`) [E0502]
    /// ```
    pub(crate) fn describe_place_for_conflicting_borrow(
        &self,
        first_borrowed_place: Place<'tcx>,
        second_borrowed_place: Place<'tcx>,
    ) -> (String, String, String, String) {
        // Define a small closure that we can use to check if the type of a place
        // is a union.
        let union_ty = |place_base| {
            // Need to use fn call syntax `PlaceRef::ty` to determine the type of `place_base`;
            // using a type annotation in the closure argument instead leads to a lifetime error.
            let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty;
            ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
        };

        // Start with an empty tuple, so we can use the functions on `Option` to reduce some
        // code duplication (particularly around returning an empty description in the failure
        // case).
        Some(())
            .filter(|_| {
                // If we have a conflicting borrow of the same place, then we don't want to add
                // an extraneous "via x.y" to our diagnostics, so filter out this case.
                first_borrowed_place != second_borrowed_place
            })
            .and_then(|_| {
                // We're going to want to traverse the first borrowed place to see if we can find
                // field access to a union. If we find that, then we will keep the place of the
                // union being accessed and the field that was being accessed so we can check the
                // second borrowed place for the same union and an access to a different field.
                for (place_base, elem) in first_borrowed_place.iter_projections().rev() {
                    match elem {
                        ProjectionElem::Field(field, _) if union_ty(place_base).is_some() => {
                            return Some((place_base, field));
                        }
                        _ => {}
                    }
                }
                None
            })
            .and_then(|(target_base, target_field)| {
                // With the place of a union and a field access into it, we traverse the second
                // borrowed place and look for an access to a different field of the same union.
                for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
                    if let ProjectionElem::Field(field, _) = elem {
                        if let Some(union_ty) = union_ty(place_base) {
                            if field != target_field && place_base == target_base {
                                return Some((
                                    self.describe_any_place(place_base),
                                    self.describe_any_place(first_borrowed_place.as_ref()),
                                    self.describe_any_place(second_borrowed_place.as_ref()),
                                    union_ty.to_string(),
                                ));
                            }
                        }
                    }
                }
                None
            })
            .unwrap_or_else(|| {
                // If we didn't find a field access into a union, or both places match, then
                // only return the description of the first place.
                (
                    self.describe_any_place(first_borrowed_place.as_ref()),
                    "".to_string(),
                    "".to_string(),
                    "".to_string(),
                )
            })
    }

    /// This means that some data referenced by `borrow` needs to live
    /// past the point where the StorageDeadOrDrop of `place` occurs.
    /// This is usually interpreted as meaning that `place` has too
    /// short a lifetime. (But sometimes it is more useful to report
    /// it as a more direct conflict between the execution of a
    /// `Drop::drop` with an aliasing borrow.)
    #[instrument(level = "debug", skip(self))]
    pub(crate) fn report_borrowed_value_does_not_live_long_enough(
        &mut self,
        location: Location,
        borrow: &BorrowData<'tcx>,
        place_span: (Place<'tcx>, Span),
        kind: Option<WriteKind>,
    ) {
        let drop_span = place_span.1;
        let borrowed_local = borrow.borrowed_place.local;

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.var_or_use_path_span();

        let proper_span = self.body.local_decls[borrowed_local].source_info.span;

        if self.access_place_error_reported.contains(&(Place::from(borrowed_local), borrow_span)) {
            debug!(
                "suppressing access_place error when borrow doesn't live long enough for {:?}",
                borrow_span
            );
            return;
        }

        self.access_place_error_reported.insert((Place::from(borrowed_local), borrow_span));

        if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
            let err =
                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
            self.buffer_error(err);
            return;
        }

        if let StorageDeadOrDrop::Destructor(dropped_ty) =
            self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
        {
            // If a borrow of path `B` conflicts with drop of `D` (and
            // we're not in the uninteresting case where `B` is a
            // prefix of `D`), then report this as a more interesting
            // destructor conflict.
            if !borrow.borrowed_place.as_ref().is_prefix_of(place_span.0.as_ref()) {
                self.report_borrow_conflicts_with_destructor(
                    location, borrow, place_span, kind, dropped_ty,
                );
                return;
            }
        }

        let place_desc = self.describe_place(borrow.borrowed_place.as_ref());

        let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
        let explanation = self.explain_why_borrow_contains_point(location, borrow, kind_place);

        debug!(?place_desc, ?explanation);

        let err = match (place_desc, explanation) {
            // If the outlives constraint comes from inside the closure,
            // for example:
            //
            // let x = 0;
            // let y = &x;
            // Box::new(|| y) as Box<Fn() -> &'static i32>
            //
            // then just use the normal error. The closure isn't escaping
            // and `move` will not help here.
            (
                Some(name),
                BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
            ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self
                .report_escaping_closure_capture(
                    borrow_spans,
                    borrow_span,
                    &RegionName {
                        name: self.synthesize_region_name(),
                        source: RegionNameSource::Static,
                    },
                    ConstraintCategory::CallArgument(None),
                    var_or_use_span,
                    &format!("`{name}`"),
                    "block",
                ),
            (
                Some(name),
                BorrowExplanation::MustBeValidFor {
                    category:
                        category @ (ConstraintCategory::Return(_)
                        | ConstraintCategory::CallArgument(_)
                        | ConstraintCategory::OpaqueType),
                    from_closure: false,
                    ref region_name,
                    span,
                    ..
                },
            ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self
                .report_escaping_closure_capture(
                    borrow_spans,
                    borrow_span,
                    region_name,
                    category,
                    span,
                    &format!("`{name}`"),
                    "function",
                ),
            (
                name,
                BorrowExplanation::MustBeValidFor {
                    category: ConstraintCategory::Assignment,
                    from_closure: false,
                    region_name:
                        RegionName {
                            source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
                            ..
                        },
                    span,
                    ..
                },
            ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
            (Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
                location,
                &name,
                borrow,
                drop_span,
                borrow_spans,
                explanation,
            ),
            (None, explanation) => self.report_temporary_value_does_not_live_long_enough(
                location,
                borrow,
                drop_span,
                borrow_spans,
                proper_span,
                explanation,
            ),
        };

        self.buffer_error(err);
    }

    fn report_local_value_does_not_live_long_enough(
        &self,
        location: Location,
        name: &str,
        borrow: &BorrowData<'tcx>,
        drop_span: Span,
        borrow_spans: UseSpans<'tcx>,
        explanation: BorrowExplanation<'tcx>,
    ) -> Diag<'tcx> {
        debug!(
            "report_local_value_does_not_live_long_enough(\
             {:?}, {:?}, {:?}, {:?}, {:?}\
             )",
            location, name, borrow, drop_span, borrow_spans
        );

        let borrow_span = borrow_spans.var_or_use_path_span();
        if let BorrowExplanation::MustBeValidFor {
            category,
            span,
            ref opt_place_desc,
            from_closure: false,
            ..
        } = explanation
        {
            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
                borrow,
                borrow_span,
                span,
                category,
                opt_place_desc.as_ref(),
            ) {
                return diag;
            }
        }

        let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`"));

        if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
            let region_name = annotation.emit(self, &mut err);

            err.span_label(
                borrow_span,
                format!("`{name}` would have to be valid for `{region_name}`..."),
            );

            err.span_label(
                drop_span,
                format!(
                    "...but `{}` will be dropped here, when the {} returns",
                    name,
                    self.infcx
                        .tcx
                        .opt_item_name(self.mir_def_id().to_def_id())
                        .map(|name| format!("function `{name}`"))
                        .unwrap_or_else(|| {
                            match &self.infcx.tcx.def_kind(self.mir_def_id()) {
                                DefKind::Closure
                                    if self
                                        .infcx
                                        .tcx
                                        .is_coroutine(self.mir_def_id().to_def_id()) =>
                                {
                                    "enclosing coroutine"
                                }
                                DefKind::Closure => "enclosing closure",
                                kind => bug!("expected closure or coroutine, found {:?}", kind),
                            }
                            .to_string()
                        })
                ),
            );

            err.note(
                "functions cannot return a borrow to data owned within the function's scope, \
                    functions can only return borrows to data passed as arguments",
            );
            err.note(
                "to learn more, visit <https://doc.rust-lang.org/book/ch04-02-\
                    references-and-borrowing.html#dangling-references>",
            );

            if let BorrowExplanation::MustBeValidFor { .. } = explanation {
            } else {
                explanation.add_explanation_to_diagnostic(
                    self.infcx.tcx,
                    self.body,
                    &self.local_names,
                    &mut err,
                    "",
                    None,
                    None,
                );
            }
        } else {
            err.span_label(borrow_span, "borrowed value does not live long enough");
            err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));

            borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
                crate::session_diagnostics::CaptureArgLabel::Capture {
                    is_within: borrow_spans.for_coroutine(),
                    args_span,
                }
            });

            explanation.add_explanation_to_diagnostic(
                self.infcx.tcx,
                self.body,
                &self.local_names,
                &mut err,
                "",
                Some(borrow_span),
                None,
            );
        }

        err
    }

    fn report_borrow_conflicts_with_destructor(
        &mut self,
        location: Location,
        borrow: &BorrowData<'tcx>,
        (place, drop_span): (Place<'tcx>, Span),
        kind: Option<WriteKind>,
        dropped_ty: Ty<'tcx>,
    ) {
        debug!(
            "report_borrow_conflicts_with_destructor(\
             {:?}, {:?}, ({:?}, {:?}), {:?}\
             )",
            location, borrow, place, drop_span, kind,
        );

        let borrow_spans = self.retrieve_borrow_spans(borrow);
        let borrow_span = borrow_spans.var_or_use();

        let mut err = self.cannot_borrow_across_destructor(borrow_span);

        let what_was_dropped = match self.describe_place(place.as_ref()) {
            Some(name) => format!("`{name}`"),
            None => String::from("temporary value"),
        };

        let label = match self.describe_place(borrow.borrowed_place.as_ref()) {
            Some(borrowed) => format!(
                "here, drop of {what_was_dropped} needs exclusive access to `{borrowed}`, \
                 because the type `{dropped_ty}` implements the `Drop` trait"
            ),
            None => format!(
                "here is drop of {what_was_dropped}; whose type `{dropped_ty}` implements the `Drop` trait"
            ),
        };
        err.span_label(drop_span, label);

        // Only give this note and suggestion if they could be relevant.
        let explanation =
            self.explain_why_borrow_contains_point(location, borrow, kind.map(|k| (k, place)));
        match explanation {
            BorrowExplanation::UsedLater { .. }
            | BorrowExplanation::UsedLaterWhenDropped { .. } => {
                err.note("consider using a `let` binding to create a longer lived value");
            }
            _ => {}
        }

        explanation.add_explanation_to_diagnostic(
            self.infcx.tcx,
            self.body,
            &self.local_names,
            &mut err,
            "",
            None,
            None,
        );

        self.buffer_error(err);
    }

    fn report_thread_local_value_does_not_live_long_enough(
        &self,
        drop_span: Span,
        borrow_span: Span,
    ) -> Diag<'tcx> {
        debug!(
            "report_thread_local_value_does_not_live_long_enough(\
             {:?}, {:?}\
             )",
            drop_span, borrow_span
        );

        self.thread_local_value_does_not_live_long_enough(borrow_span)
            .with_span_label(
                borrow_span,
                "thread-local variables cannot be borrowed beyond the end of the function",
            )
            .with_span_label(drop_span, "end of enclosing function is here")
    }

    #[instrument(level = "debug", skip(self))]
    fn report_temporary_value_does_not_live_long_enough(
        &self,
        location: Location,
        borrow: &BorrowData<'tcx>,
        drop_span: Span,
        borrow_spans: UseSpans<'tcx>,
        proper_span: Span,
        explanation: BorrowExplanation<'tcx>,
    ) -> Diag<'tcx> {
        if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
            explanation
        {
            if let Some(diag) = self.try_report_cannot_return_reference_to_local(
                borrow,
                proper_span,
                span,
                category,
                None,
            ) {
                return diag;
            }
        }

        let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
        err.span_label(proper_span, "creates a temporary value which is freed while still in use");
        err.span_label(drop_span, "temporary value is freed at the end of this statement");

        match explanation {
            BorrowExplanation::UsedLater(..)
            | BorrowExplanation::UsedLaterInLoop(..)
            | BorrowExplanation::UsedLaterWhenDropped { .. } => {
                // Only give this note and suggestion if it could be relevant.
                let sm = self.infcx.tcx.sess.source_map();
                let mut suggested = false;
                let msg = "consider using a `let` binding to create a longer lived value";

                /// We check that there's a single level of block nesting to ensure always correct
                /// suggestions. If we don't, then we only provide a free-form message to avoid
                /// misleading users in cases like `tests/ui/nll/borrowed-temporary-error.rs`.
                /// We could expand the analysis to suggest hoising all of the relevant parts of
                /// the users' code to make the code compile, but that could be too much.
                /// We found the `prop_expr` by the way to check whether the expression is a `FormatArguments`,
                /// which is a special case since it's generated by the compiler.
                struct NestedStatementVisitor<'tcx> {
                    span: Span,
                    current: usize,
                    found: usize,
                    prop_expr: Option<&'tcx hir::Expr<'tcx>>,
                    call: Option<&'tcx hir::Expr<'tcx>>,
                }

                impl<'tcx> Visitor<'tcx> for NestedStatementVisitor<'tcx> {
                    fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
                        self.current += 1;
                        walk_block(self, block);
                        self.current -= 1;
                    }
                    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                        if let hir::ExprKind::MethodCall(_, rcvr, _, _) = expr.kind {
                            if self.span == rcvr.span.source_callsite() {
                                self.call = Some(expr);
                            }
                        }
                        if self.span == expr.span.source_callsite() {
                            self.found = self.current;
                            if self.prop_expr.is_none() {
                                self.prop_expr = Some(expr);
                            }
                        }
                        walk_expr(self, expr);
                    }
                }
                let source_info = self.body.source_info(location);
                let proper_span = proper_span.source_callsite();
                if let Some(scope) = self.body.source_scopes.get(source_info.scope)
                    && let ClearCrossCrate::Set(scope_data) = &scope.local_data
                    && let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id()
                    && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
                {
                    for stmt in block.stmts {
                        let mut visitor = NestedStatementVisitor {
                            span: proper_span,
                            current: 0,
                            found: 0,
                            prop_expr: None,
                            call: None,
                        };
                        visitor.visit_stmt(stmt);

                        let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
                        let expr_ty: Option<Ty<'_>> =
                            visitor.prop_expr.map(|expr| typeck_results.expr_ty(expr).peel_refs());

                        let is_format_arguments_item = if let Some(expr_ty) = expr_ty
                            && let ty::Adt(adt, _) = expr_ty.kind()
                        {
                            self.infcx.tcx.lang_items().get(LangItem::FormatArguments)
                                == Some(adt.did())
                        } else {
                            false
                        };

                        if visitor.found == 0
                            && stmt.span.contains(proper_span)
                            && let Some(p) = sm.span_to_margin(stmt.span)
                            && let Ok(s) = sm.span_to_snippet(proper_span)
                        {
                            if let Some(call) = visitor.call
                                && let hir::ExprKind::MethodCall(path, _, [], _) = call.kind
                                && path.ident.name == sym::iter
                                && let Some(ty) = expr_ty
                            {
                                err.span_suggestion_verbose(
                                    path.ident.span,
                                    format!(
                                        "consider consuming the `{ty}` when turning it into an \
                                         `Iterator`",
                                    ),
                                    "into_iter",
                                    Applicability::MaybeIncorrect,
                                );
                            }
                            if !is_format_arguments_item {
                                let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
                                err.multipart_suggestion_verbose(
                                    msg,
                                    vec![
                                        (stmt.span.shrink_to_lo(), addition),
                                        (proper_span, "binding".to_string()),
                                    ],
                                    Applicability::MaybeIncorrect,
                                );
                            } else {
                                err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used");
                                err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
                            }
                            suggested = true;
                            break;
                        }
                    }
                }
                if !suggested {
                    err.note(msg);
                }
            }
            _ => {}
        }
        explanation.add_explanation_to_diagnostic(
            self.infcx.tcx,
            self.body,
            &self.local_names,
            &mut err,
            "",
            None,
            None,
        );

        borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
            crate::session_diagnostics::CaptureArgLabel::Capture {
                is_within: borrow_spans.for_coroutine(),
                args_span,
            }
        });

        err
    }

    fn try_report_cannot_return_reference_to_local(
        &self,
        borrow: &BorrowData<'tcx>,
        borrow_span: Span,
        return_span: Span,
        category: ConstraintCategory<'tcx>,
        opt_place_desc: Option<&String>,
    ) -> Option<Diag<'tcx>> {
        let return_kind = match category {
            ConstraintCategory::Return(_) => "return",
            ConstraintCategory::Yield => "yield",
            _ => return None,
        };

        // FIXME use a better heuristic than Spans
        let reference_desc = if return_span == self.body.source_info(borrow.reserve_location).span {
            "reference to"
        } else {
            "value referencing"
        };

        let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
            let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
                match self.body.local_kind(local) {
                    LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
                        "local variable "
                    }
                    LocalKind::Arg
                        if !self.upvars.is_empty() && local == ty::CAPTURE_STRUCT_LOCAL =>
                    {
                        "variable captured by `move` "
                    }
                    LocalKind::Arg => "function parameter ",
                    LocalKind::ReturnPointer | LocalKind::Temp => {
                        bug!("temporary or return pointer with a name")
                    }
                }
            } else {
                "local data "
            };
            (format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here"))
        } else {
            let local = borrow.borrowed_place.local;
            match self.body.local_kind(local) {
                LocalKind::Arg => (
                    "function parameter".to_string(),
                    "function parameter borrowed here".to_string(),
                ),
                LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
                    ("local binding".to_string(), "local binding introduced here".to_string())
                }
                LocalKind::ReturnPointer | LocalKind::Temp => {
                    ("temporary value".to_string(), "temporary value created here".to_string())
                }
            }
        };

        let mut err = self.cannot_return_reference_to_local(
            return_span,
            return_kind,
            reference_desc,
            &place_desc,
        );

        if return_span != borrow_span {
            err.span_label(borrow_span, note);

            let tcx = self.infcx.tcx;

            let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;

            // to avoid panics
            if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
                && self
                    .infcx
                    .type_implements_trait(iter_trait, [return_ty], self.param_env)
                    .must_apply_modulo_regions()
            {
                err.span_suggestion_hidden(
                    return_span.shrink_to_hi(),
                    "use `.collect()` to allocate the iterator",
                    ".collect::<Vec<_>>()",
                    Applicability::MaybeIncorrect,
                );
            }
        }

        Some(err)
    }

    #[instrument(level = "debug", skip(self))]
    fn report_escaping_closure_capture(
        &self,
        use_span: UseSpans<'tcx>,
        var_span: Span,
        fr_name: &RegionName,
        category: ConstraintCategory<'tcx>,
        constraint_span: Span,
        captured_var: &str,
        scope: &str,
    ) -> Diag<'tcx> {
        let tcx = self.infcx.tcx;
        let args_span = use_span.args_or_use();

        let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
            Ok(string) => {
                let coro_prefix = if string.starts_with("async") {
                    // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` to `u32`
                    Some(5)
                } else if string.starts_with("gen") {
                    // `gen` is 3 chars long
                    Some(3)
                } else {
                    None
                };
                if let Some(n) = coro_prefix {
                    let pos = args_span.lo() + BytePos(n);
                    (args_span.with_lo(pos).with_hi(pos), " move")
                } else {
                    (args_span.shrink_to_lo(), "move ")
                }
            }
            Err(_) => (args_span, "move |<args>| <body>"),
        };
        let kind = match use_span.coroutine_kind() {
            Some(coroutine_kind) => match coroutine_kind {
                CoroutineKind::Desugared(CoroutineDesugaring::Gen, kind) => match kind {
                    CoroutineSource::Block => "gen block",
                    CoroutineSource::Closure => "gen closure",
                    CoroutineSource::Fn => {
                        bug!("gen block/closure expected, but gen function found.")
                    }
                },
                CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, kind) => match kind {
                    CoroutineSource::Block => "async gen block",
                    CoroutineSource::Closure => "async gen closure",
                    CoroutineSource::Fn => {
                        bug!("gen block/closure expected, but gen function found.")
                    }
                },
                CoroutineKind::Desugared(CoroutineDesugaring::Async, async_kind) => {
                    match async_kind {
                        CoroutineSource::Block => "async block",
                        CoroutineSource::Closure => "async closure",
                        CoroutineSource::Fn => {
                            bug!("async block/closure expected, but async function found.")
                        }
                    }
                }
                CoroutineKind::Coroutine(_) => "coroutine",
            },
            None => "closure",
        };

        let mut err = self.cannot_capture_in_long_lived_closure(
            args_span,
            kind,
            captured_var,
            var_span,
            scope,
        );
        err.span_suggestion_verbose(
            sugg_span,
            format!(
                "to force the {kind} to take ownership of {captured_var} (and any \
                 other referenced variables), use the `move` keyword"
            ),
            suggestion,
            Applicability::MachineApplicable,
        );

        match category {
            ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
                let msg = format!("{kind} is returned here");
                err.span_note(constraint_span, msg);
            }
            ConstraintCategory::CallArgument(_) => {
                fr_name.highlight_region_name(&mut err);
                if matches!(
                    use_span.coroutine_kind(),
                    Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _))
                ) {
                    err.note(
                        "async blocks are not executed immediately and must either take a \
                         reference or ownership of outside variables they use",
                    );
                } else {
                    let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
                    err.span_note(constraint_span, msg);
                }
            }
            _ => bug!(
                "report_escaping_closure_capture called with unexpected constraint \
                 category: `{:?}`",
                category
            ),
        }

        err
    }

    fn report_escaping_data(
        &self,
        borrow_span: Span,
        name: &Option<String>,
        upvar_span: Span,
        upvar_name: Symbol,
        escape_span: Span,
    ) -> Diag<'tcx> {
        let tcx = self.infcx.tcx;

        let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());

        let mut err =
            borrowck_errors::borrowed_data_escapes_closure(tcx, escape_span, escapes_from);

        err.span_label(
            upvar_span,
            format!("`{upvar_name}` declared here, outside of the {escapes_from} body"),
        );

        err.span_label(borrow_span, format!("borrow is only valid in the {escapes_from} body"));

        if let Some(name) = name {
            err.span_label(
                escape_span,
                format!("reference to `{name}` escapes the {escapes_from} body here"),
            );
        } else {
            err.span_label(escape_span, format!("reference escapes the {escapes_from} body here"));
        }

        err
    }

    fn get_moved_indexes(
        &self,
        location: Location,
        mpi: MovePathIndex,
    ) -> (Vec<MoveSite>, Vec<Location>) {
        fn predecessor_locations<'tcx, 'a>(
            body: &'a mir::Body<'tcx>,
            location: Location,
        ) -> impl Iterator<Item = Location> + Captures<'tcx> + 'a {
            if location.statement_index == 0 {
                let predecessors = body.basic_blocks.predecessors()[location.block].to_vec();
                Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb)))
            } else {
                Either::Right(std::iter::once(Location {
                    statement_index: location.statement_index - 1,
                    ..location
                }))
            }
        }

        let mut mpis = vec![mpi];
        let move_paths = &self.move_data.move_paths;
        mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi));

        let mut stack = Vec::new();
        let mut back_edge_stack = Vec::new();

        predecessor_locations(self.body, location).for_each(|predecessor| {
            if location.dominates(predecessor, self.dominators()) {
                back_edge_stack.push(predecessor)
            } else {
                stack.push(predecessor);
            }
        });

        let mut reached_start = false;

        /* Check if the mpi is initialized as an argument */
        let mut is_argument = false;
        for arg in self.body.args_iter() {
            if let Some(path) = self.move_data.rev_lookup.find_local(arg) {
                if mpis.contains(&path) {
                    is_argument = true;
                }
            }
        }

        let mut visited = FxIndexSet::default();
        let mut move_locations = FxIndexSet::default();
        let mut reinits = vec![];
        let mut result = vec![];

        let mut dfs_iter = |result: &mut Vec<MoveSite>, location: Location, is_back_edge: bool| {
            debug!(
                "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})",
                location, is_back_edge
            );

            if !visited.insert(location) {
                return true;
            }

            // check for moves
            let stmt_kind =
                self.body[location.block].statements.get(location.statement_index).map(|s| &s.kind);
            if let Some(StatementKind::StorageDead(..)) = stmt_kind {
                // this analysis only tries to find moves explicitly
                // written by the user, so we ignore the move-outs
                // created by `StorageDead` and at the beginning
                // of a function.
            } else {
                // If we are found a use of a.b.c which was in error, then we want to look for
                // moves not only of a.b.c but also a.b and a.
                //
                // Note that the moves data already includes "parent" paths, so we don't have to
                // worry about the other case: that is, if there is a move of a.b.c, it is already
                // marked as a move of a.b and a as well, so we will generate the correct errors
                // there.
                for moi in &self.move_data.loc_map[location] {
                    debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
                    let path = self.move_data.moves[*moi].path;
                    if mpis.contains(&path) {
                        debug!(
                            "report_use_of_moved_or_uninitialized: found {:?}",
                            move_paths[path].place
                        );
                        result.push(MoveSite { moi: *moi, traversed_back_edge: is_back_edge });
                        move_locations.insert(location);

                        // Strictly speaking, we could continue our DFS here. There may be
                        // other moves that can reach the point of error. But it is kind of
                        // confusing to highlight them.
                        //
                        // Example:
                        //
                        // ```
                        // let a = vec![];
                        // let b = a;
                        // let c = a;
                        // drop(a); // <-- current point of error
                        // ```
                        //
                        // Because we stop the DFS here, we only highlight `let c = a`,
                        // and not `let b = a`. We will of course also report an error at
                        // `let c = a` which highlights `let b = a` as the move.
                        return true;
                    }
                }
            }

            // check for inits
            let mut any_match = false;
            for ii in &self.move_data.init_loc_map[location] {
                let init = self.move_data.inits[*ii];
                match init.kind {
                    InitKind::Deep | InitKind::NonPanicPathOnly => {
                        if mpis.contains(&init.path) {
                            any_match = true;
                        }
                    }
                    InitKind::Shallow => {
                        if mpi == init.path {
                            any_match = true;
                        }
                    }
                }
            }
            if any_match {
                reinits.push(location);
                return true;
            }
            return false;
        };

        while let Some(location) = stack.pop() {
            if dfs_iter(&mut result, location, false) {
                continue;
            }

            let mut has_predecessor = false;
            predecessor_locations(self.body, location).for_each(|predecessor| {
                if location.dominates(predecessor, self.dominators()) {
                    back_edge_stack.push(predecessor)
                } else {
                    stack.push(predecessor);
                }
                has_predecessor = true;
            });

            if !has_predecessor {
                reached_start = true;
            }
        }
        if (is_argument || !reached_start) && result.is_empty() {
            /* Process back edges (moves in future loop iterations) only if
               the move path is definitely initialized upon loop entry,
               to avoid spurious "in previous iteration" errors.
               During DFS, if there's a path from the error back to the start
               of the function with no intervening init or move, then the
               move path may be uninitialized at loop entry.
            */
            while let Some(location) = back_edge_stack.pop() {
                if dfs_iter(&mut result, location, true) {
                    continue;
                }

                predecessor_locations(self.body, location)
                    .for_each(|predecessor| back_edge_stack.push(predecessor));
            }
        }

        // Check if we can reach these reinits from a move location.
        let reinits_reachable = reinits
            .into_iter()
            .filter(|reinit| {
                let mut visited = FxIndexSet::default();
                let mut stack = vec![*reinit];
                while let Some(location) = stack.pop() {
                    if !visited.insert(location) {
                        continue;
                    }
                    if move_locations.contains(&location) {
                        return true;
                    }
                    stack.extend(predecessor_locations(self.body, location));
                }
                false
            })
            .collect::<Vec<Location>>();
        (result, reinits_reachable)
    }

    pub(crate) fn report_illegal_mutation_of_borrowed(
        &mut self,
        location: Location,
        (place, span): (Place<'tcx>, Span),
        loan: &BorrowData<'tcx>,
    ) {
        let loan_spans = self.retrieve_borrow_spans(loan);
        let loan_span = loan_spans.args_or_use();

        let descr_place = self.describe_any_place(place.as_ref());
        if let BorrowKind::Fake(_) = loan.kind {
            if let Some(section) = self.classify_immutable_section(loan.assigned_place) {
                let mut err = self.cannot_mutate_in_immutable_section(
                    span,
                    loan_span,
                    &descr_place,
                    section,
                    "assign",
                );

                loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
                    use crate::session_diagnostics::CaptureVarCause::*;
                    match kind {
                        hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
                        hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                            BorrowUseInClosure { var_span }
                        }
                    }
                });

                self.buffer_error(err);

                return;
            }
        }

        let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);

        loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
            use crate::session_diagnostics::CaptureVarCause::*;
            match kind {
                hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
                hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
                    BorrowUseInClosure { var_span }
                }
            }
        });

        self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
            self.infcx.tcx,
            self.body,
            &self.local_names,
            &mut err,
            "",
            None,
            None,
        );

        self.explain_deref_coercion(loan, &mut err);

        self.buffer_error(err);
    }

    fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diag<'_>) {
        let tcx = self.infcx.tcx;
        if let (
            Some(Terminator {
                kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
                ..
            }),
            Some((method_did, method_args)),
        ) = (
            &self.body[loan.reserve_location.block].terminator,
            rustc_middle::util::find_self_call(
                tcx,
                self.body,
                loan.assigned_place.local,
                loan.reserve_location.block,
            ),
        ) {
            if tcx.is_diagnostic_item(sym::deref_method, method_did) {
                let deref_target =
                    tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
                        Instance::resolve(tcx, self.param_env, deref_target, method_args)
                            .transpose()
                    });
                if let Some(Ok(instance)) = deref_target {
                    let deref_target_ty = instance.ty(tcx, self.param_env);
                    err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
                    err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
                }
            }
        }
    }

    /// Reports an illegal reassignment; for example, an assignment to
    /// (part of) a non-`mut` local that occurs potentially after that
    /// local has already been initialized. `place` is the path being
    /// assigned; `err_place` is a place providing a reason why
    /// `place` is not mutable (e.g., the non-`mut` local `x` in an
    /// assignment to `x.f`).
    pub(crate) fn report_illegal_reassignment(
        &mut self,
        (place, span): (Place<'tcx>, Span),
        assigned_span: Span,
        err_place: Place<'tcx>,
    ) {
        let (from_arg, local_decl, local_name) = match err_place.as_local() {
            Some(local) => (
                self.body.local_kind(local) == LocalKind::Arg,
                Some(&self.body.local_decls[local]),
                self.local_names[local],
            ),
            None => (false, None, None),
        };

        // If root local is initialized immediately (everything apart from let
        // PATTERN;) then make the error refer to that local, rather than the
        // place being assigned later.
        let (place_description, assigned_span) = match local_decl {
            Some(LocalDecl {
                local_info:
                    ClearCrossCrate::Set(
                        box LocalInfo::User(BindingForm::Var(VarBindingForm {
                            opt_match_place: None,
                            ..
                        }))
                        | box LocalInfo::StaticRef { .. }
                        | box LocalInfo::Boring,
                    ),
                ..
            })
            | None => (self.describe_any_place(place.as_ref()), assigned_span),
            Some(decl) => (self.describe_any_place(err_place.as_ref()), decl.source_info.span),
        };
        let mut err = self.cannot_reassign_immutable(span, &place_description, from_arg);
        let msg = if from_arg {
            "cannot assign to immutable argument"
        } else {
            "cannot assign twice to immutable variable"
        };
        if span != assigned_span && !from_arg {
            err.span_label(assigned_span, format!("first assignment to {place_description}"));
        }
        if let Some(decl) = local_decl
            && let Some(name) = local_name
            && decl.can_be_made_mutable()
        {
            err.span_suggestion(
                decl.source_info.span,
                "consider making this binding mutable",
                format!("mut {name}"),
                Applicability::MachineApplicable,
            );
            if !from_arg
                && matches!(
                    decl.local_info(),
                    LocalInfo::User(BindingForm::Var(VarBindingForm {
                        opt_match_place: Some((Some(_), _)),
                        ..
                    }))
                )
            {
                err.span_suggestion(
                    decl.source_info.span,
                    "to modify the original value, take a borrow instead",
                    format!("ref mut {name}"),
                    Applicability::MaybeIncorrect,
                );
            }
        }
        err.span_label(span, msg);
        self.buffer_error(err);
    }

    fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
        let tcx = self.infcx.tcx;
        let (kind, _place_ty) = place.projection.iter().fold(
            (LocalStorageDead, PlaceTy::from_ty(self.body.local_decls[place.local].ty)),
            |(kind, place_ty), &elem| {
                (
                    match elem {
                        ProjectionElem::Deref => match kind {
                            StorageDeadOrDrop::LocalStorageDead
                            | StorageDeadOrDrop::BoxedStorageDead => {
                                assert!(
                                    place_ty.ty.is_box(),
                                    "Drop of value behind a reference or raw pointer"
                                );
                                StorageDeadOrDrop::BoxedStorageDead
                            }
                            StorageDeadOrDrop::Destructor(_) => kind,
                        },
                        ProjectionElem::OpaqueCast { .. }
                        | ProjectionElem::Field(..)
                        | ProjectionElem::Downcast(..) => {
                            match place_ty.ty.kind() {
                                ty::Adt(def, _) if def.has_dtor(tcx) => {
                                    // Report the outermost adt with a destructor
                                    match kind {
                                        StorageDeadOrDrop::Destructor(_) => kind,
                                        StorageDeadOrDrop::LocalStorageDead
                                        | StorageDeadOrDrop::BoxedStorageDead => {
                                            StorageDeadOrDrop::Destructor(place_ty.ty)
                                        }
                                    }
                                }
                                _ => kind,
                            }
                        }
                        ProjectionElem::ConstantIndex { .. }
                        | ProjectionElem::Subslice { .. }
                        | ProjectionElem::Subtype(_)
                        | ProjectionElem::Index(_) => kind,
                    },
                    place_ty.projection_ty(tcx, elem),
                )
            },
        );
        kind
    }

    /// Describe the reason for the fake borrow that was assigned to `place`.
    fn classify_immutable_section(&self, place: Place<'tcx>) -> Option<&'static str> {
        use rustc_middle::mir::visit::Visitor;
        struct FakeReadCauseFinder<'tcx> {
            place: Place<'tcx>,
            cause: Option<FakeReadCause>,
        }
        impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> {
            fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
                match statement {
                    Statement { kind: StatementKind::FakeRead(box (cause, place)), .. }
                        if *place == self.place =>
                    {
                        self.cause = Some(*cause);
                    }
                    _ => (),
                }
            }
        }
        let mut visitor = FakeReadCauseFinder { place, cause: None };
        visitor.visit_body(self.body);
        match visitor.cause {
            Some(FakeReadCause::ForMatchGuard) => Some("match guard"),
            Some(FakeReadCause::ForIndex) => Some("indexing expression"),
            _ => None,
        }
    }

    /// Annotate argument and return type of function and closure with (synthesized) lifetime for
    /// borrow of local value that does not live long enough.
    fn annotate_argument_and_return_for_borrow(
        &self,
        borrow: &BorrowData<'tcx>,
    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
        // Define a fallback for when we can't match a closure.
        let fallback = || {
            let is_closure = self.infcx.tcx.is_closure_like(self.mir_def_id().to_def_id());
            if is_closure {
                None
            } else {
                let ty = self.infcx.tcx.type_of(self.mir_def_id()).instantiate_identity();
                match ty.kind() {
                    ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
                        self.mir_def_id(),
                        self.infcx.tcx.fn_sig(self.mir_def_id()).instantiate_identity(),
                    ),
                    _ => None,
                }
            }
        };

        // In order to determine whether we need to annotate, we need to check whether the reserve
        // place was an assignment into a temporary.
        //
        // If it was, we check whether or not that temporary is eventually assigned into the return
        // place. If it was, we can add annotations about the function's return type and arguments
        // and it'll make sense.
        let location = borrow.reserve_location;
        debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
        if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
            &self.body[location.block].statements.get(location.statement_index)
        {
            debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
            // Check that the initial assignment of the reserve location is into a temporary.
            let mut target = match reservation.as_local() {
                Some(local) if self.body.local_kind(local) == LocalKind::Temp => local,
                _ => return None,
            };

            // Next, look through the rest of the block, checking if we are assigning the
            // `target` (that is, the place that contains our borrow) to anything.
            let mut annotated_closure = None;
            for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
                debug!(
                    "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
                    target, stmt
                );
                if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind {
                    if let Some(assigned_to) = place.as_local() {
                        debug!(
                            "annotate_argument_and_return_for_borrow: assigned_to={:?} \
                             rvalue={:?}",
                            assigned_to, rvalue
                        );
                        // Check if our `target` was captured by a closure.
                        if let Rvalue::Aggregate(
                            box AggregateKind::Closure(def_id, args),
                            operands,
                        ) = rvalue
                        {
                            let def_id = def_id.expect_local();
                            for operand in operands {
                                let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
                                    operand
                                else {
                                    continue;
                                };
                                debug!(
                                    "annotate_argument_and_return_for_borrow: assigned_from={:?}",
                                    assigned_from
                                );

                                // Find the local from the operand.
                                let Some(assigned_from_local) =
                                    assigned_from.local_or_deref_local()
                                else {
                                    continue;
                                };

                                if assigned_from_local != target {
                                    continue;
                                }

                                // If a closure captured our `target` and then assigned
                                // into a place then we should annotate the closure in
                                // case it ends up being assigned into the return place.
                                annotated_closure =
                                    self.annotate_fn_sig(def_id, args.as_closure().sig());
                                debug!(
                                    "annotate_argument_and_return_for_borrow: \
                                     annotated_closure={:?} assigned_from_local={:?} \
                                     assigned_to={:?}",
                                    annotated_closure, assigned_from_local, assigned_to
                                );

                                if assigned_to == mir::RETURN_PLACE {
                                    // If it was assigned directly into the return place, then
                                    // return now.
                                    return annotated_closure;
                                } else {
                                    // Otherwise, update the target.
                                    target = assigned_to;
                                }
                            }

                            // If none of our closure's operands matched, then skip to the next
                            // statement.
                            continue;
                        }

                        // Otherwise, look at other types of assignment.
                        let assigned_from = match rvalue {
                            Rvalue::Ref(_, _, assigned_from) => assigned_from,
                            Rvalue::Use(operand) => match operand {
                                Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
                                    assigned_from
                                }
                                _ => continue,
                            },
                            _ => continue,
                        };
                        debug!(
                            "annotate_argument_and_return_for_borrow: \
                             assigned_from={:?}",
                            assigned_from,
                        );

                        // Find the local from the rvalue.
                        let Some(assigned_from_local) = assigned_from.local_or_deref_local() else {
                            continue;
                        };
                        debug!(
                            "annotate_argument_and_return_for_borrow: \
                             assigned_from_local={:?}",
                            assigned_from_local,
                        );

                        // Check if our local matches the target - if so, we've assigned our
                        // borrow to a new place.
                        if assigned_from_local != target {
                            continue;
                        }

                        // If we assigned our `target` into a new place, then we should
                        // check if it was the return place.
                        debug!(
                            "annotate_argument_and_return_for_borrow: \
                             assigned_from_local={:?} assigned_to={:?}",
                            assigned_from_local, assigned_to
                        );
                        if assigned_to == mir::RETURN_PLACE {
                            // If it was then return the annotated closure if there was one,
                            // else, annotate this function.
                            return annotated_closure.or_else(fallback);
                        }

                        // If we didn't assign into the return place, then we just update
                        // the target.
                        target = assigned_to;
                    }
                }
            }

            // Check the terminator if we didn't find anything in the statements.
            let terminator = &self.body[location.block].terminator();
            debug!(
                "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
                target, terminator
            );
            if let TerminatorKind::Call { destination, target: Some(_), args, .. } =
                &terminator.kind
            {
                if let Some(assigned_to) = destination.as_local() {
                    debug!(
                        "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
                        assigned_to, args
                    );
                    for operand in args {
                        let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) =
                            &operand.node
                        else {
                            continue;
                        };
                        debug!(
                            "annotate_argument_and_return_for_borrow: assigned_from={:?}",
                            assigned_from,
                        );

                        if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
                            debug!(
                                "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
                                assigned_from_local,
                            );

                            if assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
                                return annotated_closure.or_else(fallback);
                            }
                        }
                    }
                }
            }
        }

        // If we haven't found an assignment into the return place, then we need not add
        // any annotations.
        debug!("annotate_argument_and_return_for_borrow: none found");
        None
    }

    /// Annotate the first argument and return type of a function signature if they are
    /// references.
    fn annotate_fn_sig(
        &self,
        did: LocalDefId,
        sig: ty::PolyFnSig<'tcx>,
    ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
        debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
        let is_closure = self.infcx.tcx.is_closure_like(did.to_def_id());
        let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
        let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;

        // We need to work out which arguments to highlight. We do this by looking
        // at the return type, where there are three cases:
        //
        // 1. If there are named arguments, then we should highlight the return type and
        //    highlight any of the arguments that are also references with that lifetime.
        //    If there are no arguments that have the same lifetime as the return type,
        //    then don't highlight anything.
        // 2. The return type is a reference with an anonymous lifetime. If this is
        //    the case, then we can take advantage of (and teach) the lifetime elision
        //    rules.
        //
        //    We know that an error is being reported. So the arguments and return type
        //    must satisfy the elision rules. Therefore, if there is a single argument
        //    then that means the return type and first (and only) argument have the same
        //    lifetime and the borrow isn't meeting that, we can highlight the argument
        //    and return type.
        //
        //    If there are multiple arguments then the first argument must be self (else
        //    it would not satisfy the elision rules), so we can highlight self and the
        //    return type.
        // 3. The return type is not a reference. In this case, we don't highlight
        //    anything.
        let return_ty = sig.output();
        match return_ty.skip_binder().kind() {
            ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
                // This is case 1 from above, return type is a named reference so we need to
                // search for relevant arguments.
                let mut arguments = Vec::new();
                for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
                    if let ty::Ref(argument_region, _, _) = argument.kind() {
                        if argument_region == return_region {
                            // Need to use the `rustc_middle::ty` types to compare against the
                            // `return_region`. Then use the `rustc_hir` type to get only
                            // the lifetime span.
                            if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
                                // With access to the lifetime, we can get
                                // the span of it.
                                arguments.push((*argument, lifetime.ident.span));
                            } else {
                                bug!("ty type is a ref but hir type is not");
                            }
                        }
                    }
                }

                // We need to have arguments. This shouldn't happen, but it's worth checking.
                if arguments.is_empty() {
                    return None;
                }

                // We use a mix of the HIR and the Ty types to get information
                // as the HIR doesn't have full types for closure arguments.
                let return_ty = sig.output().skip_binder();
                let mut return_span = fn_decl.output.span();
                if let hir::FnRetTy::Return(ty) = &fn_decl.output {
                    if let hir::TyKind::Ref(lifetime, _) = ty.kind {
                        return_span = lifetime.ident.span;
                    }
                }

                Some(AnnotatedBorrowFnSignature::NamedFunction {
                    arguments,
                    return_ty,
                    return_span,
                })
            }
            ty::Ref(_, _, _) if is_closure => {
                // This is case 2 from above but only for closures, return type is anonymous
                // reference so we select
                // the first argument.
                let argument_span = fn_decl.inputs.first()?.span;
                let argument_ty = sig.inputs().skip_binder().first()?;

                // Closure arguments are wrapped in a tuple, so we need to get the first
                // from that.
                if let ty::Tuple(elems) = argument_ty.kind() {
                    let &argument_ty = elems.first()?;
                    if let ty::Ref(_, _, _) = argument_ty.kind() {
                        return Some(AnnotatedBorrowFnSignature::Closure {
                            argument_ty,
                            argument_span,
                        });
                    }
                }

                None
            }
            ty::Ref(_, _, _) => {
                // This is also case 2 from above but for functions, return type is still an
                // anonymous reference so we select the first argument.
                let argument_span = fn_decl.inputs.first()?.span;
                let argument_ty = *sig.inputs().skip_binder().first()?;

                let return_span = fn_decl.output.span();
                let return_ty = sig.output().skip_binder();

                // We expect the first argument to be a reference.
                match argument_ty.kind() {
                    ty::Ref(_, _, _) => {}
                    _ => return None,
                }

                Some(AnnotatedBorrowFnSignature::AnonymousFunction {
                    argument_ty,
                    argument_span,
                    return_ty,
                    return_span,
                })
            }
            _ => {
                // This is case 3 from above, return type is not a reference so don't highlight
                // anything.
                None
            }
        }
    }
}

#[derive(Debug)]
enum AnnotatedBorrowFnSignature<'tcx> {
    NamedFunction {
        arguments: Vec<(Ty<'tcx>, Span)>,
        return_ty: Ty<'tcx>,
        return_span: Span,
    },
    AnonymousFunction {
        argument_ty: Ty<'tcx>,
        argument_span: Span,
        return_ty: Ty<'tcx>,
        return_span: Span,
    },
    Closure {
        argument_ty: Ty<'tcx>,
        argument_span: Span,
    },
}

impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
    /// Annotate the provided diagnostic with information about borrow from the fn signature that
    /// helps explain.
    pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, 'tcx>, diag: &mut Diag<'_>) -> String {
        match self {
            &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
                diag.span_label(
                    argument_span,
                    format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)),
                );

                cx.get_region_name_for_ty(argument_ty, 0)
            }
            &AnnotatedBorrowFnSignature::AnonymousFunction {
                argument_ty,
                argument_span,
                return_ty,
                return_span,
            } => {
                let argument_ty_name = cx.get_name_for_ty(argument_ty, 0);
                diag.span_label(argument_span, format!("has type `{argument_ty_name}`"));

                let return_ty_name = cx.get_name_for_ty(return_ty, 0);
                let types_equal = return_ty_name == argument_ty_name;
                diag.span_label(
                    return_span,
                    format!(
                        "{}has type `{}`",
                        if types_equal { "also " } else { "" },
                        return_ty_name,
                    ),
                );

                diag.note(
                    "argument and return type have the same lifetime due to lifetime elision rules",
                );
                diag.note(
                    "to learn more, visit <https://doc.rust-lang.org/book/ch10-03-\
                     lifetime-syntax.html#lifetime-elision>",
                );

                cx.get_region_name_for_ty(return_ty, 0)
            }
            AnnotatedBorrowFnSignature::NamedFunction { arguments, return_ty, return_span } => {
                // Region of return type and arguments checked to be the same earlier.
                let region_name = cx.get_region_name_for_ty(*return_ty, 0);
                for (_, argument_span) in arguments {
                    diag.span_label(*argument_span, format!("has lifetime `{region_name}`"));
                }

                diag.span_label(*return_span, format!("also has lifetime `{region_name}`",));

                diag.help(format!(
                    "use data from the highlighted arguments which match the `{region_name}` lifetime of \
                     the return type",
                ));

                region_name
            }
        }
    }
}

/// Detect whether one of the provided spans is a statement nested within the top-most visited expr
struct ReferencedStatementsVisitor<'a>(&'a [Span], bool);

impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> {
    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
        match s.kind {
            hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => {
                self.1 = true;
            }
            _ => {}
        }
    }
}

/// Look for `break` expressions within any arbitrary expressions. We'll do this to infer
/// whether this is a case where the moved value would affect the exit of a loop, making it
/// unsuitable for a `.clone()` suggestion.
struct BreakFinder {
    found_breaks: Vec<(hir::Destination, Span)>,
    found_continues: Vec<(hir::Destination, Span)>,
}
impl<'hir> Visitor<'hir> for BreakFinder {
    fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
        match ex.kind {
            hir::ExprKind::Break(destination, _) => {
                self.found_breaks.push((destination, ex.span));
            }
            hir::ExprKind::Continue(destination) => {
                self.found_continues.push((destination, ex.span));
            }
            _ => {}
        }
        hir::intravisit::walk_expr(self, ex);
    }
}

/// Given a set of spans representing statements initializing the relevant binding, visit all the
/// function expressions looking for branching code paths that *do not* initialize the binding.
struct ConditionVisitor<'b> {
    spans: &'b [Span],
    name: &'b str,
    errors: Vec<(Span, String)>,
}

impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
        match ex.kind {
            hir::ExprKind::If(cond, body, None) => {
                // `if` expressions with no `else` that initialize the binding might be missing an
                // `else` arm.
                let mut v = ReferencedStatementsVisitor(self.spans, false);
                v.visit_expr(body);
                if v.1 {
                    self.errors.push((
                        cond.span,
                        format!(
                            "if this `if` condition is `false`, {} is not initialized",
                            self.name,
                        ),
                    ));
                    self.errors.push((
                        ex.span.shrink_to_hi(),
                        format!("an `else` arm might be missing here, initializing {}", self.name),
                    ));
                }
            }
            hir::ExprKind::If(cond, body, Some(other)) => {
                // `if` expressions where the binding is only initialized in one of the two arms
                // might be missing a binding initialization.
                let mut a = ReferencedStatementsVisitor(self.spans, false);
                a.visit_expr(body);
                let mut b = ReferencedStatementsVisitor(self.spans, false);
                b.visit_expr(other);
                match (a.1, b.1) {
                    (true, true) | (false, false) => {}
                    (true, false) => {
                        if other.span.is_desugaring(DesugaringKind::WhileLoop) {
                            self.errors.push((
                                cond.span,
                                format!(
                                    "if this condition isn't met and the `while` loop runs 0 \
                                     times, {} is not initialized",
                                    self.name
                                ),
                            ));
                        } else {
                            self.errors.push((
                                body.span.shrink_to_hi().until(other.span),
                                format!(
                                    "if the `if` condition is `false` and this `else` arm is \
                                     executed, {} is not initialized",
                                    self.name
                                ),
                            ));
                        }
                    }
                    (false, true) => {
                        self.errors.push((
                            cond.span,
                            format!(
                                "if this condition is `true`, {} is not initialized",
                                self.name
                            ),
                        ));
                    }
                }
            }
            hir::ExprKind::Match(e, arms, loop_desugar) => {
                // If the binding is initialized in one of the match arms, then the other match
                // arms might be missing an initialization.
                let results: Vec<bool> = arms
                    .iter()
                    .map(|arm| {
                        let mut v = ReferencedStatementsVisitor(self.spans, false);
                        v.visit_arm(arm);
                        v.1
                    })
                    .collect();
                if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
                    for (arm, seen) in arms.iter().zip(results) {
                        if !seen {
                            if loop_desugar == hir::MatchSource::ForLoopDesugar {
                                self.errors.push((
                                    e.span,
                                    format!(
                                        "if the `for` loop runs 0 times, {} is not initialized",
                                        self.name
                                    ),
                                ));
                            } else if let Some(guard) = &arm.guard {
                                self.errors.push((
                                    arm.pat.span.to(guard.span),
                                    format!(
                                        "if this pattern and condition are matched, {} is not \
                                         initialized",
                                        self.name
                                    ),
                                ));
                            } else {
                                self.errors.push((
                                    arm.pat.span,
                                    format!(
                                        "if this pattern is matched, {} is not initialized",
                                        self.name
                                    ),
                                ));
                            }
                        }
                    }
                }
            }
            // FIXME: should we also account for binops, particularly `&&` and `||`? `try` should
            // also be accounted for. For now it is fine, as if we don't find *any* relevant
            // branching code paths, we point at the places where the binding *is* initialized for
            // *some* context.
            _ => {}
        }
        walk_expr(self, ex);
    }
}
