use rustc_abi::FieldIdx;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::find_attr;
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::bug;
use rustc_middle::mir::visit::{
    MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::{Analysis, Backward, ResultsCursor};
use rustc_session::lint;
use rustc_span::Span;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{Symbol, kw, sym};

use crate::errors;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum AccessKind {
    Param,
    Assign,
    Capture,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CaptureKind {
    Closure(ty::ClosureKind),
    Coroutine,
    CoroutineClosure,
    None,
}

#[derive(Copy, Clone, Debug)]
struct Access {
    /// Describe the current access.
    kind: AccessKind,
    /// Is the accessed place is live at the current statement?
    /// When we encounter multiple statements at the same location, we only increase the liveness,
    /// in order to avoid false positives.
    live: bool,
}

#[tracing::instrument(level = "debug", skip(tcx), ret)]
pub(crate) fn check_liveness<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> DenseBitSet<FieldIdx> {
    // Don't run on synthetic MIR, as that will ICE trying to access HIR.
    if tcx.is_synthetic_mir(def_id) {
        return DenseBitSet::new_empty(0);
    }

    // Don't run unused pass for intrinsics
    if tcx.intrinsic(def_id.to_def_id()).is_some() {
        return DenseBitSet::new_empty(0);
    }

    // Don't run unused pass for #[naked]
    if find_attr!(tcx.get_all_attrs(def_id.to_def_id()), AttributeKind::Naked(..)) {
        return DenseBitSet::new_empty(0);
    }

    // Don't run unused pass for #[derive]
    let parent = tcx.parent(tcx.typeck_root_def_id(def_id.to_def_id()));
    if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent)
        && find_attr!(tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..))
    {
        return DenseBitSet::new_empty(0);
    }

    let mut body = &*tcx.mir_promoted(def_id).0.borrow();
    let mut body_mem;

    // Don't run if there are errors.
    if body.tainted_by_errors.is_some() {
        return DenseBitSet::new_empty(0);
    }

    let mut checked_places = PlaceSet::default();
    checked_places.insert_locals(&body.local_decls);

    // The body is the one of a closure or generator, so we also want to analyse captures.
    let (capture_kind, num_captures) = if tcx.is_closure_like(def_id.to_def_id()) {
        let mut self_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
        let mut self_is_ref = false;
        if let ty::Ref(_, ty, _) = self_ty.kind() {
            self_ty = *ty;
            self_is_ref = true;
        }

        let (capture_kind, args) = match self_ty.kind() {
            ty::Closure(_, args) => {
                (CaptureKind::Closure(args.as_closure().kind()), ty::UpvarArgs::Closure(args))
            }
            &ty::Coroutine(_, args) => (CaptureKind::Coroutine, ty::UpvarArgs::Coroutine(args)),
            &ty::CoroutineClosure(_, args) => {
                (CaptureKind::CoroutineClosure, ty::UpvarArgs::CoroutineClosure(args))
            }
            _ => bug!("expected closure or generator, found {:?}", self_ty),
        };

        let captures = tcx.closure_captures(def_id);
        checked_places.insert_captures(tcx, self_is_ref, captures, args.upvar_tys());

        // `FnMut` closures can modify captured values and carry those
        // modified values with them in subsequent calls. To model this behaviour,
        // we consider the `FnMut` closure as jumping to `bb0` upon return.
        if let CaptureKind::Closure(ty::ClosureKind::FnMut) = capture_kind {
            // FIXME: stop cloning the body.
            body_mem = body.clone();
            for bbdata in body_mem.basic_blocks_mut() {
                // We can call a closure again, either after a normal return or an unwind.
                if let TerminatorKind::Return | TerminatorKind::UnwindResume =
                    bbdata.terminator().kind
                {
                    bbdata.terminator_mut().kind = TerminatorKind::Goto { target: START_BLOCK };
                }
            }
            body = &body_mem;
        }

        (capture_kind, args.upvar_tys().len())
    } else {
        (CaptureKind::None, 0)
    };

    // Get the remaining variables' names from debuginfo.
    checked_places.record_debuginfo(&body.var_debug_info);

    let self_assignment = find_self_assignments(&checked_places, body);

    let mut live =
        MaybeLivePlaces { tcx, capture_kind, checked_places: &checked_places, self_assignment }
            .iterate_to_fixpoint(tcx, body, None)
            .into_results_cursor(body);

    let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());

    let mut assignments =
        AssignmentResult::find_dead_assignments(tcx, typing_env, &checked_places, &mut live, body);

    assignments.merge_guards();

    let dead_captures = assignments.compute_dead_captures(num_captures);

    assignments.report_fully_unused();
    assignments.report_unused_assignments();

    dead_captures
}

/// Small helper to make semantics easier to read.
#[inline]
fn is_capture(place: PlaceRef<'_>) -> bool {
    if !place.projection.is_empty() {
        debug_assert_eq!(place.local, ty::CAPTURE_STRUCT_LOCAL);
        true
    } else {
        false
    }
}

/// Give a diagnostic when any of the string constants look like a naked format string that would
/// interpolate our dead local.
fn maybe_suggest_literal_matching_name(
    body: &Body<'_>,
    name: Symbol,
) -> Vec<errors::UnusedVariableStringInterp> {
    struct LiteralFinder<'body, 'tcx> {
        body: &'body Body<'tcx>,
        name: String,
        name_colon: String,
        found: Vec<errors::UnusedVariableStringInterp>,
    }

    impl<'tcx> Visitor<'tcx> for LiteralFinder<'_, 'tcx> {
        fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, loc: Location) {
            if let ty::Ref(_, ref_ty, _) = constant.ty().kind()
                && ref_ty.kind() == &ty::Str
            {
                let rendered_constant = constant.const_.to_string();
                if rendered_constant.contains(&self.name)
                    || rendered_constant.contains(&self.name_colon)
                {
                    let lit = self.body.source_info(loc).span;
                    self.found.push(errors::UnusedVariableStringInterp { lit });
                }
            }
        }
    }

    let mut finder = LiteralFinder {
        body,
        name: format!("{{{name}}}"),
        name_colon: format!("{{{name}:"),
        found: vec![],
    };
    finder.visit_body(body);
    finder.found
}

/// Give a diagnostic when an unused variable may be a typo of a unit variant or a struct.
fn maybe_suggest_unit_pattern_typo<'tcx>(
    tcx: TyCtxt<'tcx>,
    body_def_id: DefId,
    name: Symbol,
    span: Span,
    ty: Ty<'tcx>,
) -> Option<errors::PatternTypo> {
    if let ty::Adt(adt_def, _) = ty.peel_refs().kind() {
        let variant_names: Vec<_> = adt_def
            .variants()
            .iter()
            .filter(|v| matches!(v.ctor, Some((CtorKind::Const, _))))
            .map(|v| v.name)
            .collect();
        if let Some(name) = find_best_match_for_name(&variant_names, name, None)
            && let Some(variant) = adt_def
                .variants()
                .iter()
                .find(|v| v.name == name && matches!(v.ctor, Some((CtorKind::Const, _))))
        {
            return Some(errors::PatternTypo {
                span,
                code: with_no_trimmed_paths!(tcx.def_path_str(variant.def_id)),
                kind: tcx.def_descr(variant.def_id),
                item_name: variant.name,
            });
        }
    }

    // Look for consts of the same type with similar names as well,
    // not just unit structs and variants.
    let constants = tcx
        .hir_body_owners()
        .filter(|&def_id| {
            matches!(tcx.def_kind(def_id), DefKind::Const)
                && tcx.type_of(def_id).instantiate_identity() == ty
                && tcx.visibility(def_id).is_accessible_from(body_def_id, tcx)
        })
        .collect::<Vec<_>>();
    let names = constants.iter().map(|&def_id| tcx.item_name(def_id)).collect::<Vec<_>>();
    if let Some(item_name) = find_best_match_for_name(&names, name, None)
        && let Some(position) = names.iter().position(|&n| n == item_name)
        && let Some(&def_id) = constants.get(position)
    {
        return Some(errors::PatternTypo {
            span,
            code: with_no_trimmed_paths!(tcx.def_path_str(def_id)),
            kind: "constant",
            item_name,
        });
    }

    None
}

/// Return whether we should consider the current place as a drop guard and skip reporting.
fn maybe_drop_guard<'tcx>(
    tcx: TyCtxt<'tcx>,
    typing_env: ty::TypingEnv<'tcx>,
    index: PlaceIndex,
    ever_dropped: &DenseBitSet<PlaceIndex>,
    checked_places: &PlaceSet<'tcx>,
    body: &Body<'tcx>,
) -> bool {
    if ever_dropped.contains(index) {
        let ty = checked_places.places[index].ty(&body.local_decls, tcx).ty;
        matches!(
            ty.kind(),
            ty::Closure(..)
                | ty::Coroutine(..)
                | ty::Tuple(..)
                | ty::Adt(..)
                | ty::Dynamic(..)
                | ty::Array(..)
                | ty::Slice(..)
                | ty::Alias(ty::Opaque, ..)
        ) && ty.needs_drop(tcx, typing_env)
    } else {
        false
    }
}

/// Detect the following case
///
/// ```text
/// fn change_object(mut a: &Ty) {
///     let a = Ty::new();
///     b = &a;
/// }
/// ```
///
/// where the user likely meant to modify the value behind there reference, use `a` as an out
/// parameter, instead of mutating the local binding. When encountering this we suggest:
///
/// ```text
/// fn change_object(a: &'_ mut Ty) {
///     let a = Ty::new();
///     *b = a;
/// }
/// ```
fn annotate_mut_binding_to_immutable_binding<'tcx>(
    tcx: TyCtxt<'tcx>,
    place: PlaceRef<'tcx>,
    body_def_id: LocalDefId,
    assignment_span: Span,
    body: &Body<'tcx>,
) -> Option<errors::UnusedAssignSuggestion> {
    use rustc_hir as hir;
    use rustc_hir::intravisit::{self, Visitor};

    // Verify we have a mutable argument...
    let local = place.as_local()?;
    let LocalKind::Arg = body.local_kind(local) else { return None };
    let Mutability::Mut = body.local_decls[local].mutability else { return None };

    // ... with reference type...
    let hir_param_index =
        local.as_usize() - if tcx.is_closure_like(body_def_id.to_def_id()) { 2 } else { 1 };
    let fn_decl = tcx.hir_node_by_def_id(body_def_id).fn_decl()?;
    let ty = fn_decl.inputs[hir_param_index];
    let hir::TyKind::Ref(lt, mut_ty) = ty.kind else { return None };

    // ... as a binding pattern.
    let hir_body = tcx.hir_maybe_body_owned_by(body_def_id)?;
    let param = hir_body.params[hir_param_index];
    let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = param.pat.kind else {
        return None;
    };

    // Find the assignment to modify.
    let mut finder = ExprFinder { assignment_span, lhs: None, rhs: None };
    finder.visit_body(hir_body);
    let lhs = finder.lhs?;
    let rhs = finder.rhs?;

    let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _mut, inner) = rhs.kind else { return None };

    // Changes to the parameter's type.
    let pre = if lt.ident.span.is_empty() { "" } else { " " };
    let ty_span = if mut_ty.mutbl.is_mut() {
        // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
        None
    } else {
        // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
        Some(mut_ty.ty.span.shrink_to_lo())
    };

    return Some(errors::UnusedAssignSuggestion {
        ty_span,
        pre,
        // Span of the `mut` before the binding.
        ty_ref_span: param.pat.span.until(ident.span),
        // Where to add a `*`.
        pre_lhs_span: lhs.span.shrink_to_lo(),
        // Where to remove the borrow.
        rhs_borrow_span: rhs.span.until(inner.span),
    });

    #[derive(Debug)]
    struct ExprFinder<'hir> {
        assignment_span: Span,
        lhs: Option<&'hir hir::Expr<'hir>>,
        rhs: Option<&'hir hir::Expr<'hir>>,
    }
    impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
        fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
            if expr.span == self.assignment_span
                && let hir::ExprKind::Assign(lhs, rhs, _) = expr.kind
            {
                self.lhs = Some(lhs);
                self.rhs = Some(rhs);
            } else {
                intravisit::walk_expr(self, expr)
            }
        }
    }
}

/// Compute self-assignments of the form `a += b`.
///
/// MIR building generates 2 statements and 1 terminator for such assignments:
/// - _temp = CheckedBinaryOp(a, b)
/// - assert(!_temp.1)
/// - a = _temp.0
///
/// This function tries to detect this pattern in order to avoid marking statement as a definition
/// and use. This will let the analysis be dictated by the next use of `a`.
///
/// Note that we will still need to account for the use of `b`.
fn find_self_assignments<'tcx>(
    checked_places: &PlaceSet<'tcx>,
    body: &Body<'tcx>,
) -> FxHashSet<Location> {
    let mut self_assign = FxHashSet::default();

    const FIELD_0: FieldIdx = FieldIdx::from_u32(0);
    const FIELD_1: FieldIdx = FieldIdx::from_u32(1);

    for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
        for (statement_index, stmt) in bb_data.statements.iter().enumerate() {
            let StatementKind::Assign(box (first_place, rvalue)) = &stmt.kind else { continue };
            match rvalue {
                // For checked binary ops, the MIR builder inserts an assertion in between.
                Rvalue::BinaryOp(
                    BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow,
                    box (Operand::Copy(lhs), _),
                ) => {
                    // Checked binary ops only appear at the end of the block, before the assertion.
                    if statement_index + 1 != bb_data.statements.len() {
                        continue;
                    }

                    let TerminatorKind::Assert {
                        cond,
                        target,
                        msg: box AssertKind::Overflow(..),
                        ..
                    } = &bb_data.terminator().kind
                    else {
                        continue;
                    };
                    let Some(assign) = body.basic_blocks[*target].statements.first() else {
                        continue;
                    };
                    let StatementKind::Assign(box (dest, Rvalue::Use(Operand::Move(temp)))) =
                        assign.kind
                    else {
                        continue;
                    };

                    if dest != *lhs {
                        continue;
                    }

                    let Operand::Move(cond) = cond else { continue };
                    let [PlaceElem::Field(FIELD_0, _)] = &temp.projection.as_slice() else {
                        continue;
                    };
                    let [PlaceElem::Field(FIELD_1, _)] = &cond.projection.as_slice() else {
                        continue;
                    };

                    // We ignore indirect self-assignment, because both occurrences of `dest` are uses.
                    let is_indirect = checked_places
                        .get(dest.as_ref())
                        .map_or(false, |(_, projections)| is_indirect(projections));
                    if is_indirect {
                        continue;
                    }

                    if first_place.local == temp.local
                        && first_place.local == cond.local
                        && first_place.projection.is_empty()
                    {
                        // Original block
                        self_assign.insert(Location {
                            block: bb,
                            statement_index: bb_data.statements.len() - 1,
                        });
                        self_assign.insert(Location {
                            block: bb,
                            statement_index: bb_data.statements.len(),
                        });
                        // Target block
                        self_assign.insert(Location { block: *target, statement_index: 0 });
                    }
                }
                // Straight self-assignment.
                Rvalue::BinaryOp(op, box (Operand::Copy(lhs), _)) => {
                    if lhs != first_place {
                        continue;
                    }

                    // We ignore indirect self-assignment, because both occurrences of `dest` are uses.
                    let is_indirect = checked_places
                        .get(first_place.as_ref())
                        .map_or(false, |(_, projections)| is_indirect(projections));
                    if is_indirect {
                        continue;
                    }

                    self_assign.insert(Location { block: bb, statement_index });

                    // Checked division verifies overflow before performing the division, so we
                    // need to go and ignore this check in the predecessor block.
                    if let BinOp::Div | BinOp::Rem = op
                        && statement_index == 0
                        && let &[pred] = body.basic_blocks.predecessors()[bb].as_slice()
                        && let TerminatorKind::Assert { msg, .. } =
                            &body.basic_blocks[pred].terminator().kind
                        && let AssertKind::Overflow(..) = **msg
                        && let len = body.basic_blocks[pred].statements.len()
                        && len >= 2
                    {
                        // BitAnd of two checks.
                        self_assign.insert(Location { block: pred, statement_index: len - 1 });
                        // `lhs == MIN`.
                        self_assign.insert(Location { block: pred, statement_index: len - 2 });
                    }
                }
                _ => {}
            }
        }
    }

    self_assign
}

#[derive(Default, Debug)]
struct PlaceSet<'tcx> {
    places: IndexVec<PlaceIndex, PlaceRef<'tcx>>,
    names: IndexVec<PlaceIndex, Option<(Symbol, Span)>>,

    /// Places corresponding to locals, common case.
    locals: IndexVec<Local, Option<PlaceIndex>>,

    // Handling of captures.
    /// If `_1` is a reference, we need to add a `Deref` to the matched place.
    capture_field_pos: usize,
    /// Captured fields.
    captures: IndexVec<FieldIdx, (PlaceIndex, bool)>,
}

impl<'tcx> PlaceSet<'tcx> {
    fn insert_locals(&mut self, decls: &IndexVec<Local, LocalDecl<'tcx>>) {
        self.locals = IndexVec::from_elem(None, &decls);
        for (local, decl) in decls.iter_enumerated() {
            // Record all user-written locals for the analysis.
            // We also keep the `RefForGuard` locals (more on that below).
            if let LocalInfo::User(BindingForm::Var(_) | BindingForm::RefForGuard(_)) =
                decl.local_info()
            {
                let index = self.places.push(local.into());
                self.locals[local] = Some(index);
                let _index = self.names.push(None);
                debug_assert_eq!(index, _index);
            }
        }
    }

    fn insert_captures(
        &mut self,
        tcx: TyCtxt<'tcx>,
        self_is_ref: bool,
        captures: &[&'tcx ty::CapturedPlace<'tcx>],
        upvars: &ty::List<Ty<'tcx>>,
    ) {
        // We should not track the environment local separately.
        debug_assert_eq!(self.locals[ty::CAPTURE_STRUCT_LOCAL], None);

        let self_place = Place {
            local: ty::CAPTURE_STRUCT_LOCAL,
            projection: tcx.mk_place_elems(if self_is_ref { &[PlaceElem::Deref] } else { &[] }),
        };
        if self_is_ref {
            self.capture_field_pos = 1;
        }

        for (f, (capture, ty)) in std::iter::zip(captures, upvars).enumerate() {
            let f = FieldIdx::from_usize(f);
            let elem = PlaceElem::Field(f, ty);
            let by_ref = matches!(capture.info.capture_kind, ty::UpvarCapture::ByRef(..));
            let place = if by_ref {
                self_place.project_deeper(&[elem, PlaceElem::Deref], tcx)
            } else {
                self_place.project_deeper(&[elem], tcx)
            };
            let index = self.places.push(place.as_ref());
            let _f = self.captures.push((index, by_ref));
            debug_assert_eq!(_f, f);

            // Record a variable name from the capture, because it is much friendlier than the
            // debuginfo name.
            self.names.insert(
                index,
                (Symbol::intern(&capture.to_string(tcx)), capture.get_path_span(tcx)),
            );
        }
    }

    fn record_debuginfo(&mut self, var_debug_info: &Vec<VarDebugInfo<'tcx>>) {
        let ignore_name = |name: Symbol| {
            name == sym::empty || name == kw::SelfLower || name.as_str().starts_with('_')
        };
        for var_debug_info in var_debug_info {
            if let VarDebugInfoContents::Place(place) = var_debug_info.value
                && let Some(index) = self.locals[place.local]
                && !ignore_name(var_debug_info.name)
            {
                self.names.get_or_insert_with(index, || {
                    (var_debug_info.name, var_debug_info.source_info.span)
                });
            }
        }

        // Discard places that will not result in a diagnostic.
        for index_opt in self.locals.iter_mut() {
            if let Some(index) = *index_opt {
                let remove = match self.names[index] {
                    None => true,
                    Some((name, _)) => ignore_name(name),
                };
                if remove {
                    *index_opt = None;
                }
            }
        }
    }

    #[inline]
    fn get(&self, place: PlaceRef<'tcx>) -> Option<(PlaceIndex, &'tcx [PlaceElem<'tcx>])> {
        if let Some(index) = self.locals[place.local] {
            return Some((index, place.projection));
        }
        if place.local == ty::CAPTURE_STRUCT_LOCAL
            && !self.captures.is_empty()
            && self.capture_field_pos < place.projection.len()
            && let PlaceElem::Field(f, _) = place.projection[self.capture_field_pos]
            && let Some((index, by_ref)) = self.captures.get(f)
        {
            let mut start = self.capture_field_pos + 1;
            if *by_ref {
                // Account for an extra Deref.
                start += 1;
            }
            // We may have an attempt to access `_1.f` as a shallow reborrow. Just ignore it.
            if start <= place.projection.len() {
                let projection = &place.projection[start..];
                return Some((*index, projection));
            }
        }
        None
    }

    fn iter(&self) -> impl Iterator<Item = (PlaceIndex, &PlaceRef<'tcx>)> {
        self.places.iter_enumerated()
    }

    fn len(&self) -> usize {
        self.places.len()
    }
}

struct AssignmentResult<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    typing_env: ty::TypingEnv<'tcx>,
    checked_places: &'a PlaceSet<'tcx>,
    body: &'a Body<'tcx>,
    /// Set of locals that are live at least once. This is used to report fully unused locals.
    ever_live: DenseBitSet<PlaceIndex>,
    /// Set of locals that have a non-trivial drop. This is used to skip reporting unused
    /// assignment if it would be used by the `Drop` impl.
    ever_dropped: DenseBitSet<PlaceIndex>,
    /// Set of assignments for each local. Here, assignment is understood in the AST sense. Any
    /// MIR that may look like an assignment (Assign, DropAndReplace, Yield, Call) are considered.
    ///
    /// For each local, we return a map: for each source position, whether the statement is live
    /// and which kind of access it performs. When we encounter multiple statements at the same
    /// location, we only increase the liveness, in order to avoid false positives.
    assignments: IndexVec<PlaceIndex, FxIndexMap<SourceInfo, Access>>,
}

impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
    /// Collect all assignments to checked locals.
    ///
    /// Assignments are collected, even if they are live. Dead assignments are reported, and live
    /// assignments are used to make diagnostics correct for match guards.
    fn find_dead_assignments(
        tcx: TyCtxt<'tcx>,
        typing_env: ty::TypingEnv<'tcx>,
        checked_places: &'a PlaceSet<'tcx>,
        cursor: &mut ResultsCursor<'_, 'tcx, MaybeLivePlaces<'_, 'tcx>>,
        body: &'a Body<'tcx>,
    ) -> AssignmentResult<'a, 'tcx> {
        let mut ever_live = DenseBitSet::new_empty(checked_places.len());
        let mut ever_dropped = DenseBitSet::new_empty(checked_places.len());
        let mut assignments = IndexVec::<PlaceIndex, FxIndexMap<_, _>>::from_elem(
            Default::default(),
            &checked_places.places,
        );

        let mut check_place =
            |place: Place<'tcx>, kind, source_info: SourceInfo, live: &DenseBitSet<PlaceIndex>| {
                if let Some((index, extra_projections)) = checked_places.get(place.as_ref()) {
                    if !is_indirect(extra_projections) {
                        match assignments[index].entry(source_info) {
                            IndexEntry::Vacant(v) => {
                                let access = Access { kind, live: live.contains(index) };
                                v.insert(access);
                            }
                            IndexEntry::Occupied(mut o) => {
                                // There were already a sighting. Mark this statement as live if it
                                // was, to avoid false positives.
                                o.get_mut().live |= live.contains(index);
                            }
                        }
                    }
                }
            };

        let mut record_drop = |place: Place<'tcx>| {
            if let Some((index, &[])) = checked_places.get(place.as_ref()) {
                ever_dropped.insert(index);
            }
        };

        for (bb, bb_data) in traversal::postorder(body) {
            cursor.seek_to_block_end(bb);
            let live = cursor.get();
            ever_live.union(live);

            let terminator = bb_data.terminator();
            match &terminator.kind {
                TerminatorKind::Call { destination: place, .. }
                | TerminatorKind::Yield { resume_arg: place, .. } => {
                    check_place(*place, AccessKind::Assign, terminator.source_info, live);
                    record_drop(*place)
                }
                TerminatorKind::Drop { place, .. } => record_drop(*place),
                TerminatorKind::InlineAsm { operands, .. } => {
                    for operand in operands {
                        if let InlineAsmOperand::Out { place: Some(place), .. }
                        | InlineAsmOperand::InOut { out_place: Some(place), .. } = operand
                        {
                            check_place(*place, AccessKind::Assign, terminator.source_info, live);
                        }
                    }
                }
                _ => {}
            }

            for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
                cursor.seek_before_primary_effect(Location { block: bb, statement_index });
                let live = cursor.get();
                ever_live.union(live);
                match &statement.kind {
                    StatementKind::Assign(box (place, _))
                    | StatementKind::SetDiscriminant { box place, .. } => {
                        check_place(*place, AccessKind::Assign, statement.source_info, live);
                    }
                    StatementKind::Retag(_, _)
                    | StatementKind::StorageLive(_)
                    | StatementKind::StorageDead(_)
                    | StatementKind::Coverage(_)
                    | StatementKind::Intrinsic(_)
                    | StatementKind::Nop
                    | StatementKind::FakeRead(_)
                    | StatementKind::PlaceMention(_)
                    | StatementKind::ConstEvalCounter
                    | StatementKind::BackwardIncompatibleDropHint { .. }
                    | StatementKind::AscribeUserType(_, _) => (),
                }
            }
        }

        // Check liveness of function arguments on entry.
        {
            cursor.seek_to_block_start(START_BLOCK);
            let live = cursor.get();
            ever_live.union(live);

            // Verify that arguments and captured values are useful.
            for (index, place) in checked_places.iter() {
                let kind = if is_capture(*place) {
                    // This is a by-ref capture, an assignment to it will modify surrounding
                    // environment, so we do not report it.
                    if place.projection.last() == Some(&PlaceElem::Deref) {
                        continue;
                    }

                    AccessKind::Capture
                } else if body.local_kind(place.local) == LocalKind::Arg {
                    AccessKind::Param
                } else {
                    continue;
                };
                let source_info = body.local_decls[place.local].source_info;
                let access = Access { kind, live: live.contains(index) };
                assignments[index].insert(source_info, access);
            }
        }

        AssignmentResult {
            tcx,
            typing_env,
            checked_places,
            ever_live,
            ever_dropped,
            assignments,
            body,
        }
    }

    /// Match guards introduce a different local to freeze the guarded value as immutable.
    /// Having two locals, we need to make sure that we do not report an unused_variable
    /// when the guard local is used but not the arm local, or vice versa, like in this example.
    ///
    ///    match 5 {
    ///      x if x > 2 => {}
    ///      ^    ^- This is `local`
    ///      +------ This is `arm_local`
    ///      _ => {}
    ///    }
    ///
    fn merge_guards(&mut self) {
        for (index, place) in self.checked_places.iter() {
            let local = place.local;
            if let &LocalInfo::User(BindingForm::RefForGuard(arm_local)) =
                self.body.local_decls[local].local_info()
            {
                debug_assert!(place.projection.is_empty());

                // Local to use in the arm.
                let Some((arm_index, _proj)) = self.checked_places.get(arm_local.into()) else {
                    continue;
                };
                debug_assert_ne!(index, arm_index);
                debug_assert_eq!(_proj, &[]);

                // Mark the arm local as used if the guard local is used.
                if self.ever_live.contains(index) {
                    self.ever_live.insert(arm_index);
                }

                // Some assignments are common to both locals in the source code.
                // Sadly, we can only detect this using the `source_info`.
                // Therefore, we loop over all the assignments we have for the guard local:
                // - if they already appeared for the arm local, the assignment is live if one of the
                //   two versions is live;
                // - if it does not appear for the arm local, it happened inside the guard, so we add
                //   it as-is.
                let guard_assignments = std::mem::take(&mut self.assignments[index]);
                let arm_assignments = &mut self.assignments[arm_index];
                for (source_info, access) in guard_assignments {
                    match arm_assignments.entry(source_info) {
                        IndexEntry::Vacant(v) => {
                            v.insert(access);
                        }
                        IndexEntry::Occupied(mut o) => {
                            o.get_mut().live |= access.live;
                        }
                    }
                }
            }
        }
    }

    /// Compute captures that are fully dead.
    fn compute_dead_captures(&self, num_captures: usize) -> DenseBitSet<FieldIdx> {
        // Report to caller the set of dead captures.
        let mut dead_captures = DenseBitSet::new_empty(num_captures);
        for (index, place) in self.checked_places.iter() {
            if self.ever_live.contains(index) {
                continue;
            }

            // This is a capture: pass information to the enclosing function.
            if is_capture(*place) {
                for p in place.projection {
                    if let PlaceElem::Field(f, _) = p {
                        dead_captures.insert(*f);
                        break;
                    }
                }
                continue;
            }
        }

        dead_captures
    }

    /// Report fully unused locals, and forget the corresponding assignments.
    fn report_fully_unused(&mut self) {
        let tcx = self.tcx;

        // First, report fully unused locals.
        for (index, place) in self.checked_places.iter() {
            if self.ever_live.contains(index) {
                continue;
            }

            // this is a capture: let the enclosing function report the unused variable.
            if is_capture(*place) {
                continue;
            }

            let local = place.local;
            let decl = &self.body.local_decls[local];

            if decl.from_compiler_desugaring() {
                continue;
            }

            // Only report actual user-defined binding from now on.
            let LocalInfo::User(BindingForm::Var(binding)) = decl.local_info() else { continue };
            let Some(hir_id) = decl.source_info.scope.lint_root(&self.body.source_scopes) else {
                continue;
            };

            let introductions = &binding.introductions;

            let Some((name, def_span)) = self.checked_places.names[index] else { continue };

            // #117284, when `ident_span` and `def_span` have different contexts
            // we can't provide a good suggestion, instead we pointed out the spans from macro
            let from_macro = def_span.from_expansion()
                && introductions.iter().any(|intro| intro.span.eq_ctxt(def_span));

            let maybe_suggest_typo = || {
                if let LocalKind::Arg = self.body.local_kind(local) {
                    None
                } else {
                    maybe_suggest_unit_pattern_typo(
                        tcx,
                        self.body.source.def_id(),
                        name,
                        def_span,
                        decl.ty,
                    )
                }
            };

            let statements = &mut self.assignments[index];
            if statements.is_empty() {
                let sugg = if from_macro {
                    errors::UnusedVariableSugg::NoSugg { span: def_span, name }
                } else {
                    let typo = maybe_suggest_typo();
                    errors::UnusedVariableSugg::TryPrefix { spans: vec![def_span], name, typo }
                };
                tcx.emit_node_span_lint(
                    lint::builtin::UNUSED_VARIABLES,
                    hir_id,
                    def_span,
                    errors::UnusedVariable {
                        name,
                        string_interp: maybe_suggest_literal_matching_name(self.body, name),
                        sugg,
                    },
                );
                continue;
            }

            // Idiomatic rust assigns a value to a local upon definition. However, we do not want to
            // warn twice, for the unused local and for the unused assignment. Therefore, we remove
            // from the list of assignments the ones that happen at the definition site.
            statements.retain(|source_info, _| {
                source_info.span.find_ancestor_inside(binding.pat_span).is_none()
            });

            // Extra assignments that we recognize thanks to the initialization span. We need to
            // take care of macro contexts here to be accurate.
            if let Some((_, initializer_span)) = binding.opt_match_place {
                statements.retain(|source_info, _| {
                    let within = source_info.span.find_ancestor_inside(initializer_span);
                    let outer_initializer_span =
                        initializer_span.find_ancestor_in_same_ctxt(source_info.span);
                    within.is_none()
                        && outer_initializer_span.map_or(true, |s| !s.contains(source_info.span))
                });
            }

            if !statements.is_empty() {
                // We have a dead local with outstanding assignments and with non-trivial drop.
                // This is probably a drop-guard, so we do not issue a warning there.
                if maybe_drop_guard(
                    tcx,
                    self.typing_env,
                    index,
                    &self.ever_dropped,
                    self.checked_places,
                    self.body,
                ) {
                    statements.clear();
                    continue;
                }

                let typo = maybe_suggest_typo();
                tcx.emit_node_span_lint(
                    lint::builtin::UNUSED_VARIABLES,
                    hir_id,
                    def_span,
                    errors::UnusedVarAssignedOnly { name, typo },
                );
                continue;
            }

            // We do not have outstanding assignments, suggest renaming the binding.
            let spans = introductions.iter().map(|intro| intro.span).collect::<Vec<_>>();

            let any_shorthand = introductions.iter().any(|intro| intro.is_shorthand);

            let sugg = if any_shorthand {
                errors::UnusedVariableSugg::TryIgnore {
                    name,
                    shorthands: introductions
                        .iter()
                        .filter_map(
                            |intro| if intro.is_shorthand { Some(intro.span) } else { None },
                        )
                        .collect(),
                    non_shorthands: introductions
                        .iter()
                        .filter_map(
                            |intro| {
                                if !intro.is_shorthand { Some(intro.span) } else { None }
                            },
                        )
                        .collect(),
                }
            } else if from_macro {
                errors::UnusedVariableSugg::NoSugg { span: def_span, name }
            } else if !introductions.is_empty() {
                let typo = maybe_suggest_typo();
                errors::UnusedVariableSugg::TryPrefix { name, typo, spans: spans.clone() }
            } else {
                let typo = maybe_suggest_typo();
                errors::UnusedVariableSugg::TryPrefix { name, typo, spans: vec![def_span] }
            };

            tcx.emit_node_span_lint(
                lint::builtin::UNUSED_VARIABLES,
                hir_id,
                spans,
                errors::UnusedVariable {
                    name,
                    string_interp: maybe_suggest_literal_matching_name(self.body, name),
                    sugg,
                },
            );
        }
    }

    /// Second, report unused assignments that do not correspond to initialization.
    /// Initializations have been removed in the previous loop reporting unused variables.
    fn report_unused_assignments(self) {
        let tcx = self.tcx;

        for (index, statements) in self.assignments.into_iter_enumerated() {
            if statements.is_empty() {
                continue;
            }

            let Some((name, decl_span)) = self.checked_places.names[index] else { continue };

            // We have outstanding assignments and with non-trivial drop.
            // This is probably a drop-guard, so we do not issue a warning there.
            if maybe_drop_guard(
                tcx,
                self.typing_env,
                index,
                &self.ever_dropped,
                self.checked_places,
                self.body,
            ) {
                continue;
            }

            // We probed MIR in reverse order for dataflow.
            // We revert the vector to give a consistent order to the user.
            for (source_info, Access { live, kind }) in statements.into_iter().rev() {
                if live {
                    continue;
                }

                // Report the dead assignment.
                let Some(hir_id) = source_info.scope.lint_root(&self.body.source_scopes) else {
                    continue;
                };

                match kind {
                    AccessKind::Assign => {
                        let suggestion = annotate_mut_binding_to_immutable_binding(
                            tcx,
                            self.checked_places.places[index],
                            self.body.source.def_id().expect_local(),
                            source_info.span,
                            self.body,
                        );
                        tcx.emit_node_span_lint(
                            lint::builtin::UNUSED_ASSIGNMENTS,
                            hir_id,
                            source_info.span,
                            errors::UnusedAssign { name, help: suggestion.is_none(), suggestion },
                        )
                    }
                    AccessKind::Param => tcx.emit_node_span_lint(
                        lint::builtin::UNUSED_ASSIGNMENTS,
                        hir_id,
                        source_info.span,
                        errors::UnusedAssignPassed { name },
                    ),
                    AccessKind::Capture => tcx.emit_node_span_lint(
                        lint::builtin::UNUSED_ASSIGNMENTS,
                        hir_id,
                        decl_span,
                        errors::UnusedCaptureMaybeCaptureRef { name },
                    ),
                }
            }
        }
    }
}

rustc_index::newtype_index! {
    pub struct PlaceIndex {}
}

impl DebugWithContext<MaybeLivePlaces<'_, '_>> for PlaceIndex {
    fn fmt_with(
        &self,
        ctxt: &MaybeLivePlaces<'_, '_>,
        f: &mut std::fmt::Formatter<'_>,
    ) -> std::fmt::Result {
        std::fmt::Debug::fmt(&ctxt.checked_places.places[*self], f)
    }
}

pub struct MaybeLivePlaces<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    checked_places: &'a PlaceSet<'tcx>,
    capture_kind: CaptureKind,
    self_assignment: FxHashSet<Location>,
}

impl<'tcx> MaybeLivePlaces<'_, 'tcx> {
    fn transfer_function<'a>(
        &'a self,
        trans: &'a mut DenseBitSet<PlaceIndex>,
    ) -> TransferFunction<'a, 'tcx> {
        TransferFunction {
            tcx: self.tcx,
            checked_places: &self.checked_places,
            capture_kind: self.capture_kind,
            trans,
            self_assignment: &self.self_assignment,
        }
    }
}

impl<'tcx> Analysis<'tcx> for MaybeLivePlaces<'_, 'tcx> {
    type Domain = DenseBitSet<PlaceIndex>;
    type Direction = Backward;

    const NAME: &'static str = "liveness-lint";

    fn bottom_value(&self, _: &Body<'tcx>) -> Self::Domain {
        // bottom = not live
        DenseBitSet::new_empty(self.checked_places.len())
    }

    fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
        // No variables are live until we observe a use
    }

    fn apply_primary_statement_effect(
        &self,
        trans: &mut Self::Domain,
        statement: &Statement<'tcx>,
        location: Location,
    ) {
        self.transfer_function(trans).visit_statement(statement, location);
    }

    fn apply_primary_terminator_effect<'mir>(
        &self,
        trans: &mut Self::Domain,
        terminator: &'mir Terminator<'tcx>,
        location: Location,
    ) -> TerminatorEdges<'mir, 'tcx> {
        self.transfer_function(trans).visit_terminator(terminator, location);
        terminator.edges()
    }

    fn apply_call_return_effect(
        &self,
        _trans: &mut Self::Domain,
        _block: BasicBlock,
        _return_places: CallReturnPlaces<'_, 'tcx>,
    ) {
        // FIXME: what should happen here?
    }
}

struct TransferFunction<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    checked_places: &'a PlaceSet<'tcx>,
    trans: &'a mut DenseBitSet<PlaceIndex>,
    capture_kind: CaptureKind,
    self_assignment: &'a FxHashSet<Location>,
}

impl<'tcx> Visitor<'tcx> for TransferFunction<'_, 'tcx> {
    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        match statement.kind {
            // `ForLet(None)` fake read erroneously marks the just-assigned local as live.
            // This defeats the purpose of the analysis for `let` bindings.
            StatementKind::FakeRead(box (FakeReadCause::ForLet(None), _)) => return,
            // Handle self-assignment by restricting the read/write they do.
            StatementKind::Assign(box (ref dest, ref rvalue))
                if self.self_assignment.contains(&location) =>
            {
                if let Rvalue::BinaryOp(
                    BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow,
                    box (_, rhs),
                ) = rvalue
                {
                    // We are computing the binary operation:
                    // - the LHS will be assigned, so we don't read it;
                    // - the RHS still needs to be read.
                    self.visit_operand(rhs, location);
                    self.visit_place(
                        dest,
                        PlaceContext::MutatingUse(MutatingUseContext::Store),
                        location,
                    );
                } else if let Rvalue::BinaryOp(_, box (_, rhs)) = rvalue {
                    // We are computing the binary operation:
                    // - the LHS is being updated, so we don't read it;
                    // - the RHS still needs to be read.
                    self.visit_operand(rhs, location);
                } else {
                    // This is the second part of a checked self-assignment,
                    // we are assigning the result.
                    // We do not consider the write to the destination as a `def`.
                    // `self_assignment` must be false if the assignment is indirect.
                    self.visit_rvalue(rvalue, location);
                }
            }
            _ => self.super_statement(statement, location),
        }
    }

    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        // By-ref captures could be read by the surrounding environment, so we mark
        // them as live upon yield and return.
        match terminator.kind {
            TerminatorKind::Return
            | TerminatorKind::Yield { .. }
            | TerminatorKind::Goto { target: START_BLOCK } // Inserted for the `FnMut` case.
                if self.capture_kind != CaptureKind::None =>
            {
                // All indirect captures have an effect on the environment, so we mark them as live.
                for (index, place) in self.checked_places.iter() {
                    if place.local == ty::CAPTURE_STRUCT_LOCAL
                        && place.projection.last() == Some(&PlaceElem::Deref)
                    {
                        self.trans.insert(index);
                    }
                }
            }
            // Do not consider a drop to be a use. We whitelist interesting drops elsewhere.
            TerminatorKind::Drop { .. } => {}
            // Ignore assertions since they must be triggered by actual code.
            TerminatorKind::Assert { .. } => {}
            _ => self.super_terminator(terminator, location),
        }
    }

    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        match rvalue {
            // When a closure/generator does not use some of its captures, do not consider these
            // captures as live in the surrounding function. This allows to report unused variables,
            // even if they have been (uselessly) captured.
            Rvalue::Aggregate(
                box AggregateKind::Closure(def_id, _) | box AggregateKind::Coroutine(def_id, _),
                operands,
            ) => {
                if let Some(def_id) = def_id.as_local() {
                    let dead_captures = self.tcx.check_liveness(def_id);
                    for (field, operand) in
                        operands.iter_enumerated().take(dead_captures.domain_size())
                    {
                        if !dead_captures.contains(field) {
                            self.visit_operand(operand, location);
                        }
                    }
                }
            }
            _ => self.super_rvalue(rvalue, location),
        }
    }

    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
        if let Some((index, extra_projections)) = self.checked_places.get(place.as_ref()) {
            for i in (extra_projections.len()..=place.projection.len()).rev() {
                let place_part =
                    PlaceRef { local: place.local, projection: &place.projection[..i] };
                let extra_projections = &place.projection[i..];

                if let Some(&elem) = extra_projections.get(0) {
                    self.visit_projection_elem(place_part, elem, context, location);
                }
            }

            match DefUse::for_place(extra_projections, context) {
                Some(DefUse::Def) => {
                    self.trans.remove(index);
                }
                Some(DefUse::Use) => {
                    self.trans.insert(index);
                }
                None => {}
            }
        } else {
            self.super_place(place, context, location)
        }
    }

    fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
        if let Some((index, _proj)) = self.checked_places.get(local.into()) {
            debug_assert_eq!(_proj, &[]);
            match DefUse::for_place(&[], context) {
                Some(DefUse::Def) => {
                    self.trans.remove(index);
                }
                Some(DefUse::Use) => {
                    self.trans.insert(index);
                }
                _ => {}
            }
        }
    }
}

#[derive(Eq, PartialEq, Debug, Clone)]
enum DefUse {
    Def,
    Use,
}

fn is_indirect(proj: &[PlaceElem<'_>]) -> bool {
    proj.iter().any(|p| p.is_indirect())
}

impl DefUse {
    fn for_place<'tcx>(projection: &[PlaceElem<'tcx>], context: PlaceContext) -> Option<DefUse> {
        let is_indirect = is_indirect(projection);
        match context {
            PlaceContext::MutatingUse(
                MutatingUseContext::Store | MutatingUseContext::SetDiscriminant,
            ) => {
                if is_indirect {
                    // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a
                    // use.
                    Some(DefUse::Use)
                } else if projection.is_empty() {
                    Some(DefUse::Def)
                } else {
                    None
                }
            }

            // For the associated terminators, this is only a `Def` when the terminator returns
            // "successfully." As such, we handle this case separately in `call_return_effect`
            // above. However, if the place looks like `*_5`, this is still unconditionally a use of
            // `_5`.
            PlaceContext::MutatingUse(
                MutatingUseContext::Call
                | MutatingUseContext::Yield
                | MutatingUseContext::AsmOutput,
            ) => is_indirect.then_some(DefUse::Use),

            // All other contexts are uses...
            PlaceContext::MutatingUse(
                MutatingUseContext::RawBorrow
                | MutatingUseContext::Borrow
                | MutatingUseContext::Drop
                | MutatingUseContext::Retag,
            )
            | PlaceContext::NonMutatingUse(
                NonMutatingUseContext::RawBorrow
                | NonMutatingUseContext::Copy
                | NonMutatingUseContext::Inspect
                | NonMutatingUseContext::Move
                | NonMutatingUseContext::FakeBorrow
                | NonMutatingUseContext::SharedBorrow
                | NonMutatingUseContext::PlaceMention,
            ) => Some(DefUse::Use),

            PlaceContext::NonUse(
                NonUseContext::StorageLive
                | NonUseContext::StorageDead
                | NonUseContext::AscribeUserTy(_)
                | NonUseContext::BackwardIncompatibleDropHint
                | NonUseContext::VarDebugInfo,
            ) => None,

            PlaceContext::MutatingUse(MutatingUseContext::Projection)
            | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
                unreachable!("A projection could be a def or a use and must be handled separately")
            }
        }
    }
}
