// This implements the dead-code warning pass.
// All reachable symbols are live, code called from live code is live, code with certain lint
// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else
// is dead.

use std::mem;
use std::ops::ControlFlow;

use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
use rustc_abi::FieldIdx;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Node, PatKind, QPath};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::privacy::Level;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, AssocTag, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::DEAD_CODE;
use rustc_session::lint::{self, LintExpectationId};
use rustc_span::{Symbol, kw, sym};

use crate::errors::{
    ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
};

/// Any local definition that may call something in its body block should be explored. For example,
/// if it's a live function, then we should explore its block to check for codes that may need to
/// be marked as live.
fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
    match tcx.def_kind(def_id) {
        DefKind::Mod
        | DefKind::Struct
        | DefKind::Union
        | DefKind::Enum
        | DefKind::Variant
        | DefKind::Trait
        | DefKind::TyAlias
        | DefKind::ForeignTy
        | DefKind::TraitAlias
        | DefKind::AssocTy
        | DefKind::Fn
        | DefKind::Const
        | DefKind::Static { .. }
        | DefKind::AssocFn
        | DefKind::AssocConst
        | DefKind::Macro(_)
        | DefKind::GlobalAsm
        | DefKind::Impl { .. }
        | DefKind::OpaqueTy
        | DefKind::AnonConst
        | DefKind::InlineConst
        | DefKind::ExternCrate
        | DefKind::Use
        | DefKind::Ctor(..)
        | DefKind::ForeignMod => true,

        DefKind::TyParam
        | DefKind::ConstParam
        | DefKind::Field
        | DefKind::LifetimeParam
        | DefKind::Closure
        | DefKind::SyntheticCoroutineBody => false,
    }
}

/// Determine if a work from the worklist is coming from a `#[allow]`
/// or a `#[expect]` of `dead_code`
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
enum ComesFromAllowExpect {
    Yes,
    No,
}

struct MarkSymbolVisitor<'tcx> {
    worklist: Vec<(LocalDefId, ComesFromAllowExpect)>,
    tcx: TyCtxt<'tcx>,
    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
    scanned: LocalDefIdSet,
    live_symbols: LocalDefIdSet,
    repr_unconditionally_treats_fields_as_live: bool,
    repr_has_repr_simd: bool,
    in_pat: bool,
    ignore_variant_stack: Vec<DefId>,
    // maps from ADTs to ignored derived traits (e.g. Debug and Clone)
    // and the span of their respective impl (i.e., part of the derive
    // macro)
    ignored_derived_traits: LocalDefIdMap<FxIndexSet<DefId>>,
}

impl<'tcx> MarkSymbolVisitor<'tcx> {
    /// Gets the type-checking results for the current body.
    /// As this will ICE if called outside bodies, only call when working with
    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
    #[track_caller]
    fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
        self.maybe_typeck_results
            .expect("`MarkSymbolVisitor::typeck_results` called outside of body")
    }

    fn check_def_id(&mut self, def_id: DefId) {
        if let Some(def_id) = def_id.as_local() {
            if should_explore(self.tcx, def_id) {
                self.worklist.push((def_id, ComesFromAllowExpect::No));
            }
            self.live_symbols.insert(def_id);
        }
    }

    fn insert_def_id(&mut self, def_id: DefId) {
        if let Some(def_id) = def_id.as_local() {
            debug_assert!(!should_explore(self.tcx, def_id));
            self.live_symbols.insert(def_id);
        }
    }

    fn handle_res(&mut self, res: Res) {
        match res {
            Res::Def(
                DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
                def_id,
            ) => {
                self.check_def_id(def_id);
            }
            _ if self.in_pat => {}
            Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {}
            Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => {
                let variant_id = self.tcx.parent(ctor_def_id);
                let enum_id = self.tcx.parent(variant_id);
                self.check_def_id(enum_id);
                if !self.ignore_variant_stack.contains(&ctor_def_id) {
                    self.check_def_id(variant_id);
                }
            }
            Res::Def(DefKind::Variant, variant_id) => {
                let enum_id = self.tcx.parent(variant_id);
                self.check_def_id(enum_id);
                if !self.ignore_variant_stack.contains(&variant_id) {
                    self.check_def_id(variant_id);
                }
            }
            Res::Def(_, def_id) => self.check_def_id(def_id),
            Res::SelfTyParam { trait_: t } => self.check_def_id(t),
            Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
            Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
        }
    }

    fn lookup_and_handle_method(&mut self, id: hir::HirId) {
        if let Some(def_id) = self.typeck_results().type_dependent_def_id(id) {
            self.check_def_id(def_id);
        } else {
            assert!(
                self.typeck_results().tainted_by_errors.is_some(),
                "no type-dependent def for method"
            );
        }
    }

    fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) {
        match self.typeck_results().expr_ty_adjusted(lhs).kind() {
            ty::Adt(def, _) => {
                let index = self.typeck_results().field_index(hir_id);
                self.insert_def_id(def.non_enum_variant().fields[index].did);
            }
            ty::Tuple(..) => {}
            ty::Error(_) => {}
            kind => span_bug!(lhs.span, "named field access on non-ADT: {kind:?}"),
        }
    }

    fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) {
        if self
            .typeck_results()
            .expr_adjustments(expr)
            .iter()
            .any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_)))
        {
            let _ = self.visit_expr(expr);
        } else if let hir::ExprKind::Field(base, ..) = expr.kind {
            // Ignore write to field
            self.handle_assign(base);
        } else {
            let _ = self.visit_expr(expr);
        }
    }

    fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) {
        fn check_for_self_assign_helper<'tcx>(
            typeck_results: &'tcx ty::TypeckResults<'tcx>,
            lhs: &'tcx hir::Expr<'tcx>,
            rhs: &'tcx hir::Expr<'tcx>,
        ) -> bool {
            match (&lhs.kind, &rhs.kind) {
                (hir::ExprKind::Path(qpath_l), hir::ExprKind::Path(qpath_r)) => {
                    if let (Res::Local(id_l), Res::Local(id_r)) = (
                        typeck_results.qpath_res(qpath_l, lhs.hir_id),
                        typeck_results.qpath_res(qpath_r, rhs.hir_id),
                    ) {
                        if id_l == id_r {
                            return true;
                        }
                    }
                    return false;
                }
                (hir::ExprKind::Field(lhs_l, ident_l), hir::ExprKind::Field(lhs_r, ident_r)) => {
                    if ident_l == ident_r {
                        return check_for_self_assign_helper(typeck_results, lhs_l, lhs_r);
                    }
                    return false;
                }
                _ => {
                    return false;
                }
            }
        }

        if let hir::ExprKind::Assign(lhs, rhs, _) = assign.kind
            && check_for_self_assign_helper(self.typeck_results(), lhs, rhs)
            && !assign.span.from_expansion()
        {
            let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));
            self.tcx.emit_node_span_lint(
                lint::builtin::DEAD_CODE,
                assign.hir_id,
                assign.span,
                UselessAssignment { is_field_assign, ty: self.typeck_results().expr_ty(lhs) },
            )
        }
    }

    fn handle_field_pattern_match(
        &mut self,
        lhs: &hir::Pat<'_>,
        res: Res,
        pats: &[hir::PatField<'_>],
    ) {
        let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
            ty::Adt(adt, _) => {
                // Marks the ADT live if its variant appears as the pattern,
                // considering cases when we have `let T(x) = foo()` and `fn foo<T>() -> T;`,
                // we will lose the liveness info of `T` cause we cannot mark it live when visiting `foo`.
                // Related issue: https://github.com/rust-lang/rust/issues/120770
                self.check_def_id(adt.did());
                adt.variant_of_res(res)
            }
            _ => span_bug!(lhs.span, "non-ADT in struct pattern"),
        };
        for pat in pats {
            if let PatKind::Wild = pat.pat.kind {
                continue;
            }
            let index = self.typeck_results().field_index(pat.hir_id);
            self.insert_def_id(variant.fields[index].did);
        }
    }

    fn handle_tuple_field_pattern_match(
        &mut self,
        lhs: &hir::Pat<'_>,
        res: Res,
        pats: &[hir::Pat<'_>],
        dotdot: hir::DotDotPos,
    ) {
        let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
            ty::Adt(adt, _) => {
                // Marks the ADT live if its variant appears as the pattern
                self.check_def_id(adt.did());
                adt.variant_of_res(res)
            }
            _ => {
                self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
                return;
            }
        };
        let dotdot = dotdot.as_opt_usize().unwrap_or(pats.len());
        let first_n = pats.iter().enumerate().take(dotdot);
        let missing = variant.fields.len() - pats.len();
        let last_n = pats.iter().enumerate().skip(dotdot).map(|(idx, pat)| (idx + missing, pat));
        for (idx, pat) in first_n.chain(last_n) {
            if let PatKind::Wild = pat.kind {
                continue;
            }
            self.insert_def_id(variant.fields[FieldIdx::from_usize(idx)].did);
        }
    }

    fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) {
        let data = self.typeck_results().offset_of_data();
        let &(container, ref indices) =
            data.get(expr.hir_id).expect("no offset_of_data for offset_of");

        let body_did = self.typeck_results().hir_owner.to_def_id();
        let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, body_did);

        let mut current_ty = container;

        for &(variant, field) in indices {
            match current_ty.kind() {
                ty::Adt(def, args) => {
                    let field = &def.variant(variant).fields[field];

                    self.insert_def_id(field.did);
                    let field_ty = field.ty(self.tcx, args);

                    current_ty = self.tcx.normalize_erasing_regions(typing_env, field_ty);
                }
                // we don't need to mark tuple fields as live,
                // but we may need to mark subfields
                ty::Tuple(tys) => {
                    current_ty =
                        self.tcx.normalize_erasing_regions(typing_env, tys[field.as_usize()]);
                }
                _ => span_bug!(expr.span, "named field access on non-ADT"),
            }
        }
    }

    fn mark_live_symbols(&mut self) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result {
        while let Some(work) = self.worklist.pop() {
            let (mut id, comes_from_allow_expect) = work;

            // in the case of tuple struct constructors we want to check the item,
            // not the generated tuple struct constructor function
            if let DefKind::Ctor(..) = self.tcx.def_kind(id) {
                id = self.tcx.local_parent(id);
            }

            // When using `#[allow]` or `#[expect]` of `dead_code`, we do a QOL improvement
            // by declaring fn calls, statics, ... within said items as live, as well as
            // the item itself, although technically this is not the case.
            //
            // This means that the lint for said items will never be fired.
            //
            // This doesn't make any difference for the item declared with `#[allow]`, as
            // the lint firing will be a nop, as it will be silenced by the `#[allow]` of
            // the item.
            //
            // However, for `#[expect]`, the presence or absence of the lint is relevant,
            // so we don't add it to the list of live symbols when it comes from a
            // `#[expect]`. This means that we will correctly report an item as live or not
            // for the `#[expect]` case.
            //
            // Note that an item can and will be duplicated on the worklist with different
            // `ComesFromAllowExpect`, particularly if it was added from the
            // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks,
            // this "duplication" is essential as otherwise a function with `#[expect]`
            // called from a `pub fn` may be falsely reported as not live, falsely
            // triggering the `unfulfilled_lint_expectations` lint.
            match comes_from_allow_expect {
                ComesFromAllowExpect::Yes => {}
                ComesFromAllowExpect::No => {
                    self.live_symbols.insert(id);
                }
            }

            if !self.scanned.insert(id) {
                continue;
            }

            // Avoid accessing the HIR for the synthesized associated type generated for RPITITs.
            if self.tcx.is_impl_trait_in_trait(id.to_def_id()) {
                self.live_symbols.insert(id);
                continue;
            }

            self.visit_node(self.tcx.hir_node_by_def_id(id))?;
        }

        ControlFlow::Continue(())
    }

    /// Automatically generated items marked with `rustc_trivial_field_reads`
    /// will be ignored for the purposes of dead code analysis (see PR #85200
    /// for discussion).
    fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool {
        if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind
            && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id())
            && self.tcx.is_automatically_derived(impl_of)
            && let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity()
            && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads)
        {
            if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind()
                && let Some(adt_def_id) = adt_def.did().as_local()
            {
                self.ignored_derived_traits.entry(adt_def_id).or_default().insert(trait_ref.def_id);
            }
            return true;
        }

        false
    }

    fn visit_node(
        &mut self,
        node: Node<'tcx>,
    ) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result {
        if let Node::ImplItem(impl_item) = node
            && self.should_ignore_impl_item(impl_item)
        {
            return ControlFlow::Continue(());
        }

        let unconditionally_treated_fields_as_live =
            self.repr_unconditionally_treats_fields_as_live;
        let had_repr_simd = self.repr_has_repr_simd;
        self.repr_unconditionally_treats_fields_as_live = false;
        self.repr_has_repr_simd = false;
        let walk_result = match node {
            Node::Item(item) => match item.kind {
                hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                    let def = self.tcx.adt_def(item.owner_id);
                    self.repr_unconditionally_treats_fields_as_live =
                        def.repr().c() || def.repr().transparent();
                    self.repr_has_repr_simd = def.repr().simd();

                    intravisit::walk_item(self, item)
                }
                hir::ItemKind::ForeignMod { .. } => ControlFlow::Continue(()),
                hir::ItemKind::Trait(.., trait_item_refs) => {
                    // mark assoc ty live if the trait is live
                    for trait_item in trait_item_refs {
                        if matches!(self.tcx.def_kind(trait_item.owner_id), DefKind::AssocTy) {
                            self.check_def_id(trait_item.owner_id.to_def_id());
                        }
                    }
                    intravisit::walk_item(self, item)
                }
                _ => intravisit::walk_item(self, item),
            },
            Node::TraitItem(trait_item) => {
                // mark the trait live
                let trait_item_id = trait_item.owner_id.to_def_id();
                if let Some(trait_id) = self.tcx.trait_of_assoc(trait_item_id) {
                    self.check_def_id(trait_id);
                }
                intravisit::walk_trait_item(self, trait_item)
            }
            Node::ImplItem(impl_item) => {
                let item = self.tcx.local_parent(impl_item.owner_id.def_id);
                if let hir::ImplItemImplKind::Inherent { .. } = impl_item.impl_kind {
                    //// If it's a type whose items are live, then it's live, too.
                    //// This is done to handle the case where, for example, the static
                    //// method of a private type is used, but the type itself is never
                    //// called directly.
                    let self_ty = self.tcx.type_of(item).instantiate_identity();
                    match *self_ty.kind() {
                        ty::Adt(def, _) => self.check_def_id(def.did()),
                        ty::Foreign(did) => self.check_def_id(did),
                        ty::Dynamic(data, ..) => {
                            if let Some(def_id) = data.principal_def_id() {
                                self.check_def_id(def_id)
                            }
                        }
                        _ => {}
                    }
                }
                intravisit::walk_impl_item(self, impl_item)
            }
            Node::ForeignItem(foreign_item) => intravisit::walk_foreign_item(self, foreign_item),
            Node::OpaqueTy(opaq) => intravisit::walk_opaque_ty(self, opaq),
            _ => ControlFlow::Continue(()),
        };
        self.repr_has_repr_simd = had_repr_simd;
        self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;

        walk_result
    }

    fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
        if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() {
            for field in fields {
                let index = self.typeck_results().field_index(field.hir_id);
                self.insert_def_id(adt.non_enum_variant().fields[index].did);
            }
        }
    }

    /// Returns whether `local_def_id` is potentially alive or not.
    /// `local_def_id` points to an impl or an impl item,
    /// both impl and impl item that may be passed to this function are of a trait,
    /// and added into the unsolved_items during `create_and_seed_worklist`
    fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool {
        let (impl_block_id, trait_def_id) = match self.tcx.def_kind(local_def_id) {
            // assoc impl items of traits are live if the corresponding trait items are live
            DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => {
                let trait_item_id =
                    self.tcx.trait_item_of(local_def_id).and_then(|def_id| def_id.as_local());
                (self.tcx.local_parent(local_def_id), trait_item_id)
            }
            // impl items are live if the corresponding traits are live
            DefKind::Impl { of_trait: true } => {
                (local_def_id, self.tcx.impl_trait_id(local_def_id).as_local())
            }
            _ => bug!(),
        };

        if let Some(trait_def_id) = trait_def_id
            && !self.live_symbols.contains(&trait_def_id)
        {
            return false;
        }

        // The impl or impl item is used if the corresponding trait or trait item is used and the ty is used.
        if let ty::Adt(adt, _) = self.tcx.type_of(impl_block_id).instantiate_identity().kind()
            && let Some(adt_def_id) = adt.did().as_local()
            && !self.live_symbols.contains(&adt_def_id)
        {
            return false;
        }

        true
    }
}

impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
    type Result = ControlFlow<ErrorGuaranteed>;

    fn visit_nested_body(&mut self, body: hir::BodyId) -> Self::Result {
        let typeck_results = self.tcx.typeck_body(body);

        // The result shouldn't be tainted, otherwise it will cause ICE.
        if let Some(guar) = typeck_results.tainted_by_errors {
            return ControlFlow::Break(guar);
        }

        let old_maybe_typeck_results = self.maybe_typeck_results.replace(typeck_results);
        let body = self.tcx.hir_body(body);
        let result = self.visit_body(body);
        self.maybe_typeck_results = old_maybe_typeck_results;

        result
    }

    fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) -> Self::Result {
        let tcx = self.tcx;
        let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
        let has_repr_simd = self.repr_has_repr_simd;
        let effective_visibilities = &tcx.effective_visibilities(());
        let live_fields = def.fields().iter().filter_map(|f| {
            let def_id = f.def_id;
            if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) {
                return Some(def_id);
            }
            if !effective_visibilities.is_reachable(f.hir_id.owner.def_id) {
                return None;
            }
            if effective_visibilities.is_reachable(def_id) { Some(def_id) } else { None }
        });
        self.live_symbols.extend(live_fields);

        intravisit::walk_struct_def(self, def)
    }

    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
        match expr.kind {
            hir::ExprKind::Path(ref qpath @ QPath::TypeRelative(..)) => {
                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
                self.handle_res(res);
            }
            hir::ExprKind::MethodCall(..) => {
                self.lookup_and_handle_method(expr.hir_id);
            }
            hir::ExprKind::Field(ref lhs, ..) => {
                if self.typeck_results().opt_field_index(expr.hir_id).is_some() {
                    self.handle_field_access(lhs, expr.hir_id);
                } else {
                    self.tcx.dcx().span_delayed_bug(expr.span, "couldn't resolve index for field");
                }
            }
            hir::ExprKind::Struct(qpath, fields, _) => {
                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
                self.handle_res(res);
                if let ty::Adt(adt, _) = self.typeck_results().expr_ty(expr).kind() {
                    self.mark_as_used_if_union(*adt, fields);
                }
            }
            hir::ExprKind::Closure(cls) => {
                self.insert_def_id(cls.def_id.to_def_id());
            }
            hir::ExprKind::OffsetOf(..) => {
                self.handle_offset_of(expr);
            }
            hir::ExprKind::Assign(ref lhs, ..) => {
                self.handle_assign(lhs);
                self.check_for_self_assign(expr);
            }
            _ => (),
        }

        intravisit::walk_expr(self, expr)
    }

    fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Self::Result {
        // Inside the body, ignore constructions of variants
        // necessary for the pattern to match. Those construction sites
        // can't be reached unless the variant is constructed elsewhere.
        let len = self.ignore_variant_stack.len();
        self.ignore_variant_stack.extend(arm.pat.necessary_variants());
        let result = intravisit::walk_arm(self, arm);
        self.ignore_variant_stack.truncate(len);

        result
    }

    fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Self::Result {
        self.in_pat = true;
        match pat.kind {
            PatKind::Struct(ref path, fields, _) => {
                let res = self.typeck_results().qpath_res(path, pat.hir_id);
                self.handle_field_pattern_match(pat, res, fields);
            }
            PatKind::TupleStruct(ref qpath, fields, dotdot) => {
                let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
                self.handle_tuple_field_pattern_match(pat, res, fields, dotdot);
            }
            _ => (),
        }

        let result = intravisit::walk_pat(self, pat);
        self.in_pat = false;

        result
    }

    fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) -> Self::Result {
        match &expr.kind {
            rustc_hir::PatExprKind::Path(qpath) => {
                // mark the type of variant live when meeting E::V in expr
                if let ty::Adt(adt, _) = self.typeck_results().node_type(expr.hir_id).kind() {
                    self.check_def_id(adt.did());
                }

                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
                self.handle_res(res);
            }
            _ => {}
        }
        intravisit::walk_pat_expr(self, expr)
    }

    fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) -> Self::Result {
        self.handle_res(path.res);
        intravisit::walk_path(self, path)
    }

    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) -> Self::Result {
        // When inline const blocks are used in pattern position, paths
        // referenced by it should be considered as used.
        let in_pat = mem::replace(&mut self.in_pat, false);

        self.live_symbols.insert(c.def_id);
        let result = intravisit::walk_anon_const(self, c);

        self.in_pat = in_pat;

        result
    }

    fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) -> Self::Result {
        // When inline const blocks are used in pattern position, paths
        // referenced by it should be considered as used.
        let in_pat = mem::replace(&mut self.in_pat, false);

        self.live_symbols.insert(c.def_id);
        let result = intravisit::walk_inline_const(self, c);

        self.in_pat = in_pat;

        result
    }

    fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) -> Self::Result {
        if let Some(trait_def_id) = t.path.res.opt_def_id()
            && let Some(segment) = t.path.segments.last()
            && let Some(args) = segment.args
        {
            for constraint in args.constraints {
                if let Some(local_def_id) = self
                    .tcx
                    .associated_items(trait_def_id)
                    .find_by_ident_and_kind(
                        self.tcx,
                        constraint.ident,
                        AssocTag::Const,
                        trait_def_id,
                    )
                    .and_then(|item| item.def_id.as_local())
                {
                    self.worklist.push((local_def_id, ComesFromAllowExpect::No));
                }
            }
        }

        intravisit::walk_trait_ref(self, t)
    }
}

fn has_allow_dead_code_or_lang_attr(
    tcx: TyCtxt<'_>,
    def_id: LocalDefId,
) -> Option<ComesFromAllowExpect> {
    fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
        tcx.has_attr(def_id, sym::lang)
            // Stable attribute for #[lang = "panic_impl"]
            || tcx.has_attr(def_id, sym::panic_handler)
    }

    fn has_allow_expect_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
        let hir_id = tcx.local_def_id_to_hir_id(def_id);
        let lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).level;
        matches!(lint_level, lint::Allow | lint::Expect)
    }

    fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
        tcx.def_kind(def_id).has_codegen_attrs() && {
            let cg_attrs = tcx.codegen_fn_attrs(def_id);

            // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
            // forcefully, e.g., for placing it in a specific section.
            cg_attrs.contains_extern_indicator()
                || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
                || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
        }
    }

    if has_allow_expect_dead_code(tcx, def_id) {
        Some(ComesFromAllowExpect::Yes)
    } else if has_used_like_attr(tcx, def_id) || has_lang_attr(tcx, def_id) {
        Some(ComesFromAllowExpect::No)
    } else {
        None
    }
}

/// Examine the given definition and record it in the worklist if it should be considered live.
///
/// We want to explicitly consider as live:
/// * Item annotated with #[allow(dead_code)]
///       This is done so that if we want to suppress warnings for a
///       group of dead functions, we only have to annotate the "root".
///       For example, if both `f` and `g` are dead and `f` calls `g`,
///       then annotating `f` with `#[allow(dead_code)]` will suppress
///       warning for both `f` and `g`.
///
/// * Item annotated with #[lang=".."]
///       Lang items are always callable from elsewhere.
///
/// For trait methods and implementations of traits, we are not certain that the definitions are
/// live at this stage. We record them in `unsolved_items` for later examination.
fn maybe_record_as_seed<'tcx>(
    tcx: TyCtxt<'tcx>,
    owner_id: hir::OwnerId,
    worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
    unsolved_items: &mut Vec<LocalDefId>,
) {
    let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, owner_id.def_id);
    if let Some(comes_from_allow) = allow_dead_code {
        worklist.push((owner_id.def_id, comes_from_allow));
    }

    match tcx.def_kind(owner_id) {
        DefKind::Enum => {
            if let Some(comes_from_allow) = allow_dead_code {
                let adt = tcx.adt_def(owner_id);
                worklist.extend(
                    adt.variants()
                        .iter()
                        .map(|variant| (variant.def_id.expect_local(), comes_from_allow)),
                );
            }
        }
        DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy => {
            if allow_dead_code.is_none() {
                let parent = tcx.local_parent(owner_id.def_id);
                match tcx.def_kind(parent) {
                    DefKind::Impl { of_trait: false } | DefKind::Trait => {}
                    DefKind::Impl { of_trait: true } => {
                        // We only care about associated items of traits,
                        // because they cannot be visited directly,
                        // so we later mark them as live if their corresponding traits
                        // or trait items and self types are both live,
                        // but inherent associated items can be visited and marked directly.
                        unsolved_items.push(owner_id.def_id);
                    }
                    _ => bug!(),
                }
            }
        }
        DefKind::Impl { of_trait: true } => {
            if allow_dead_code.is_none() {
                unsolved_items.push(owner_id.def_id);
            }
        }
        DefKind::GlobalAsm => {
            // global_asm! is always live.
            worklist.push((owner_id.def_id, ComesFromAllowExpect::No));
        }
        DefKind::Const => {
            if tcx.item_name(owner_id.def_id) == kw::Underscore {
                // `const _` is always live, as that syntax only exists for the side effects
                // of type checking and evaluating the constant expression, and marking them
                // as dead code would defeat that purpose.
                worklist.push((owner_id.def_id, ComesFromAllowExpect::No));
            }
        }
        _ => {}
    }
}

fn create_and_seed_worklist(
    tcx: TyCtxt<'_>,
) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, Vec<LocalDefId>) {
    let effective_visibilities = &tcx.effective_visibilities(());
    let mut unsolved_impl_item = Vec::new();
    let mut worklist = effective_visibilities
        .iter()
        .filter_map(|(&id, effective_vis)| {
            effective_vis
                .is_public_at_level(Level::Reachable)
                .then_some(id)
                .map(|id| (id, ComesFromAllowExpect::No))
        })
        // Seed entry point
        .chain(
            tcx.entry_fn(())
                .and_then(|(def_id, _)| def_id.as_local().map(|id| (id, ComesFromAllowExpect::No))),
        )
        .collect::<Vec<_>>();

    let crate_items = tcx.hir_crate_items(());
    for id in crate_items.owners() {
        maybe_record_as_seed(tcx, id, &mut worklist, &mut unsolved_impl_item);
    }

    (worklist, unsolved_impl_item)
}

fn live_symbols_and_ignored_derived_traits(
    tcx: TyCtxt<'_>,
    (): (),
) -> Result<(LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>), ErrorGuaranteed> {
    let (worklist, mut unsolved_items) = create_and_seed_worklist(tcx);
    let mut symbol_visitor = MarkSymbolVisitor {
        worklist,
        tcx,
        maybe_typeck_results: None,
        scanned: Default::default(),
        live_symbols: Default::default(),
        repr_unconditionally_treats_fields_as_live: false,
        repr_has_repr_simd: false,
        in_pat: false,
        ignore_variant_stack: vec![],
        ignored_derived_traits: Default::default(),
    };
    if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() {
        return Err(guar);
    }

    // We have marked the primary seeds as live. We now need to process unsolved items from traits
    // and trait impls: add them to the work list if the trait or the implemented type is live.
    let mut items_to_check: Vec<_> = unsolved_items
        .extract_if(.., |&mut local_def_id| {
            symbol_visitor.check_impl_or_impl_item_live(local_def_id)
        })
        .collect();

    while !items_to_check.is_empty() {
        symbol_visitor
            .worklist
            .extend(items_to_check.drain(..).map(|id| (id, ComesFromAllowExpect::No)));
        if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() {
            return Err(guar);
        }

        items_to_check.extend(unsolved_items.extract_if(.., |&mut local_def_id| {
            symbol_visitor.check_impl_or_impl_item_live(local_def_id)
        }));
    }

    Ok((symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits))
}

struct DeadItem {
    def_id: LocalDefId,
    name: Symbol,
    level: (lint::Level, Option<LintExpectationId>),
}

struct DeadVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    live_symbols: &'tcx LocalDefIdSet,
    ignored_derived_traits: &'tcx LocalDefIdMap<FxIndexSet<DefId>>,
}

enum ShouldWarnAboutField {
    Yes,
    No,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ReportOn {
    /// Report on something that hasn't got a proper name to refer to
    TupleField,
    /// Report on something that has got a name, which could be a field but also a method
    NamedField,
}

impl<'tcx> DeadVisitor<'tcx> {
    fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> ShouldWarnAboutField {
        if self.live_symbols.contains(&field.did.expect_local()) {
            return ShouldWarnAboutField::No;
        }
        let field_type = self.tcx.type_of(field.did).instantiate_identity();
        if field_type.is_phantom_data() {
            return ShouldWarnAboutField::No;
        }
        let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
        if is_positional
            && self
                .tcx
                .layout_of(
                    ty::TypingEnv::non_body_analysis(self.tcx, field.did)
                        .as_query_input(field_type),
                )
                .map_or(true, |layout| layout.is_zst())
        {
            return ShouldWarnAboutField::No;
        }
        ShouldWarnAboutField::Yes
    }

    fn def_lint_level(&self, id: LocalDefId) -> (lint::Level, Option<LintExpectationId>) {
        let hir_id = self.tcx.local_def_id_to_hir_id(id);
        let level = self.tcx.lint_level_at_node(DEAD_CODE, hir_id);
        (level.level, level.lint_id)
    }

    // # Panics
    // All `dead_codes` must have the same lint level, otherwise we will intentionally ICE.
    // This is because we emit a multi-spanned lint using the lint level of the `dead_codes`'s
    // first local def id.
    // Prefer calling `Self.warn_dead_code` or `Self.warn_dead_code_grouped_by_lint_level`
    // since those methods group by lint level before calling this method.
    fn lint_at_single_level(
        &self,
        dead_codes: &[&DeadItem],
        participle: &str,
        parent_item: Option<LocalDefId>,
        report_on: ReportOn,
    ) {
        let Some(&first_item) = dead_codes.first() else { return };
        let tcx = self.tcx;

        let first_lint_level = first_item.level;
        assert!(dead_codes.iter().skip(1).all(|item| item.level == first_lint_level));

        let names: Vec<_> = dead_codes.iter().map(|item| item.name).collect();
        let spans: Vec<_> = dead_codes
            .iter()
            .map(|item| {
                let span = tcx.def_span(item.def_id);
                let ident_span = tcx.def_ident_span(item.def_id);
                // FIXME(cjgillot) this SyntaxContext manipulation does not make any sense.
                ident_span.map(|s| s.with_ctxt(span.ctxt())).unwrap_or(span)
            })
            .collect();

        let mut descr = tcx.def_descr(first_item.def_id.to_def_id());
        // `impl` blocks are "batched" and (unlike other batching) might
        // contain different kinds of associated items.
        if dead_codes.iter().any(|item| tcx.def_descr(item.def_id.to_def_id()) != descr) {
            descr = "associated item"
        }

        let num = dead_codes.len();
        let multiple = num > 6;
        let name_list = names.into();

        let parent_info = parent_item.map(|parent_item| {
            let parent_descr = tcx.def_descr(parent_item.to_def_id());
            let span = if let DefKind::Impl { .. } = tcx.def_kind(parent_item) {
                tcx.def_span(parent_item)
            } else {
                tcx.def_ident_span(parent_item).unwrap()
            };
            ParentInfo { num, descr, parent_descr, span }
        });

        let mut encl_def_id = parent_item.unwrap_or(first_item.def_id);
        // `ignored_derived_traits` is computed for the enum, not for the variants.
        if let DefKind::Variant = tcx.def_kind(encl_def_id) {
            encl_def_id = tcx.local_parent(encl_def_id);
        }

        let ignored_derived_impls =
            self.ignored_derived_traits.get(&encl_def_id).map(|ign_traits| {
                let trait_list = ign_traits
                    .iter()
                    .map(|trait_id| self.tcx.item_name(*trait_id))
                    .collect::<Vec<_>>();
                let trait_list_len = trait_list.len();
                IgnoredDerivedImpls {
                    name: self.tcx.item_name(encl_def_id.to_def_id()),
                    trait_list: trait_list.into(),
                    trait_list_len,
                }
            });

        let diag = match report_on {
            ReportOn::TupleField => {
                let tuple_fields = if let Some(parent_id) = parent_item
                    && let node = tcx.hir_node_by_def_id(parent_id)
                    && let hir::Node::Item(hir::Item {
                        kind: hir::ItemKind::Struct(_, _, hir::VariantData::Tuple(fields, _, _)),
                        ..
                    }) = node
                {
                    *fields
                } else {
                    &[]
                };

                let trailing_tuple_fields = if tuple_fields.len() >= dead_codes.len() {
                    LocalDefIdSet::from_iter(
                        tuple_fields
                            .iter()
                            .skip(tuple_fields.len() - dead_codes.len())
                            .map(|f| f.def_id),
                    )
                } else {
                    LocalDefIdSet::default()
                };

                let fields_suggestion =
                    // Suggest removal if all tuple fields are at the end.
                    // Otherwise suggest removal or changing to unit type
                    if dead_codes.iter().all(|dc| trailing_tuple_fields.contains(&dc.def_id)) {
                        ChangeFields::Remove { num }
                    } else {
                        ChangeFields::ChangeToUnitTypeOrRemove { num, spans: spans.clone() }
                    };

                MultipleDeadCodes::UnusedTupleStructFields {
                    multiple,
                    num,
                    descr,
                    participle,
                    name_list,
                    change_fields_suggestion: fields_suggestion,
                    parent_info,
                    ignored_derived_impls,
                }
            }
            ReportOn::NamedField => {
                let enum_variants_with_same_name = dead_codes
                    .iter()
                    .filter_map(|dead_item| {
                        if let DefKind::AssocFn | DefKind::AssocConst =
                            tcx.def_kind(dead_item.def_id)
                            && let impl_did = tcx.local_parent(dead_item.def_id)
                            && let DefKind::Impl { of_trait: false } = tcx.def_kind(impl_did)
                            && let ty::Adt(maybe_enum, _) =
                                tcx.type_of(impl_did).instantiate_identity().kind()
                            && maybe_enum.is_enum()
                            && let Some(variant) =
                                maybe_enum.variants().iter().find(|i| i.name == dead_item.name)
                        {
                            Some(crate::errors::EnumVariantSameName {
                                dead_descr: tcx.def_descr(dead_item.def_id.to_def_id()),
                                dead_name: dead_item.name,
                                variant_span: tcx.def_span(variant.def_id),
                            })
                        } else {
                            None
                        }
                    })
                    .collect();

                MultipleDeadCodes::DeadCodes {
                    multiple,
                    num,
                    descr,
                    participle,
                    name_list,
                    parent_info,
                    ignored_derived_impls,
                    enum_variants_with_same_name,
                }
            }
        };

        let hir_id = tcx.local_def_id_to_hir_id(first_item.def_id);
        self.tcx.emit_node_span_lint(DEAD_CODE, hir_id, MultiSpan::from_spans(spans), diag);
    }

    fn warn_multiple(
        &self,
        def_id: LocalDefId,
        participle: &str,
        dead_codes: Vec<DeadItem>,
        report_on: ReportOn,
    ) {
        let mut dead_codes = dead_codes
            .iter()
            .filter(|v| !v.name.as_str().starts_with('_'))
            .collect::<Vec<&DeadItem>>();
        if dead_codes.is_empty() {
            return;
        }
        // FIXME: `dead_codes` should probably be morally equivalent to `IndexMap<(Level, LintExpectationId), (DefId, Symbol)>`
        dead_codes.sort_by_key(|v| v.level.0);
        for group in dead_codes.chunk_by(|a, b| a.level == b.level) {
            self.lint_at_single_level(&group, participle, Some(def_id), report_on);
        }
    }

    fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
        let item = DeadItem {
            def_id: id,
            name: self.tcx.item_name(id.to_def_id()),
            level: self.def_lint_level(id),
        };
        self.lint_at_single_level(&[&item], participle, None, ReportOn::NamedField);
    }

    fn check_definition(&mut self, def_id: LocalDefId) {
        if self.is_live_code(def_id) {
            return;
        }
        match self.tcx.def_kind(def_id) {
            DefKind::AssocConst
            | DefKind::AssocTy
            | DefKind::AssocFn
            | DefKind::Fn
            | DefKind::Static { .. }
            | DefKind::Const
            | DefKind::TyAlias
            | DefKind::Enum
            | DefKind::Union
            | DefKind::ForeignTy
            | DefKind::Trait => self.warn_dead_code(def_id, "used"),
            DefKind::Struct => self.warn_dead_code(def_id, "constructed"),
            DefKind::Variant | DefKind::Field => bug!("should be handled specially"),
            _ => {}
        }
    }

    fn is_live_code(&self, def_id: LocalDefId) -> bool {
        // if we cannot get a name for the item, then we just assume that it is
        // live. I mean, we can't really emit a lint.
        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
            return true;
        };

        self.live_symbols.contains(&def_id) || name.as_str().starts_with('_')
    }
}

fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
    let Ok((live_symbols, ignored_derived_traits)) =
        tcx.live_symbols_and_ignored_derived_traits(()).as_ref()
    else {
        return;
    };

    let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };

    let module_items = tcx.hir_module_items(module);

    for item in module_items.free_items() {
        let def_kind = tcx.def_kind(item.owner_id);

        let mut dead_codes = Vec::new();
        // Only diagnose unused assoc items in inherent impl and used trait,
        // for unused assoc items in impls of trait,
        // we have diagnosed them in the trait if they are unused,
        // for unused assoc items in unused trait,
        // we have diagnosed the unused trait.
        if matches!(def_kind, DefKind::Impl { of_trait: false })
            || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
        {
            for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
                if let Some(local_def_id) = def_id.as_local()
                    && !visitor.is_live_code(local_def_id)
                {
                    let name = tcx.item_name(def_id);
                    let level = visitor.def_lint_level(local_def_id);
                    dead_codes.push(DeadItem { def_id: local_def_id, name, level });
                }
            }
        }
        if !dead_codes.is_empty() {
            visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField);
        }

        if !live_symbols.contains(&item.owner_id.def_id) {
            let parent = tcx.local_parent(item.owner_id.def_id);
            if parent != module.to_local_def_id() && !live_symbols.contains(&parent) {
                // We already have diagnosed something.
                continue;
            }
            visitor.check_definition(item.owner_id.def_id);
            continue;
        }

        if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
            let adt = tcx.adt_def(item.owner_id);
            let mut dead_variants = Vec::new();

            for variant in adt.variants() {
                let def_id = variant.def_id.expect_local();
                if !live_symbols.contains(&def_id) {
                    // Record to group diagnostics.
                    let level = visitor.def_lint_level(def_id);
                    dead_variants.push(DeadItem { def_id, name: variant.name, level });
                    continue;
                }

                let is_positional = variant.fields.raw.first().is_some_and(|field| {
                    field.name.as_str().starts_with(|c: char| c.is_ascii_digit())
                });
                let report_on =
                    if is_positional { ReportOn::TupleField } else { ReportOn::NamedField };
                let dead_fields = variant
                    .fields
                    .iter()
                    .filter_map(|field| {
                        let def_id = field.did.expect_local();
                        if let ShouldWarnAboutField::Yes = visitor.should_warn_about_field(field) {
                            let level = visitor.def_lint_level(def_id);
                            Some(DeadItem { def_id, name: field.name, level })
                        } else {
                            None
                        }
                    })
                    .collect();
                visitor.warn_multiple(def_id, "read", dead_fields, report_on);
            }

            visitor.warn_multiple(
                item.owner_id.def_id,
                "constructed",
                dead_variants,
                ReportOn::NamedField,
            );
        }
    }

    for foreign_item in module_items.foreign_items() {
        visitor.check_definition(foreign_item.owner_id.def_id);
    }
}

pub(crate) fn provide(providers: &mut Providers) {
    *providers =
        Providers { live_symbols_and_ignored_derived_traits, check_mod_deathness, ..*providers };
}
