//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.

use std::mem::replace;
use std::num::NonZero;

use rustc_attr::{
    self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
    Unstable, UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
use rustc_feature::ACCEPTED_FEATURES;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
use rustc_target::spec::abi::Abi;
use tracing::{debug, info};

use crate::errors;

#[derive(PartialEq)]
enum AnnotationKind {
    /// Annotation is required if not inherited from unstable parents.
    Required,
    /// Annotation is useless, reject it.
    Prohibited,
    /// Deprecation annotation is useless, reject it. (Stability attribute is still required.)
    DeprecationProhibited,
    /// Annotation itself is useless, but it can be propagated to children.
    Container,
}

/// Whether to inherit deprecation flags for nested items. In most cases, we do want to inherit
/// deprecation, because nested items rarely have individual deprecation attributes, and so
/// should be treated as deprecated if their parent is. However, default generic parameters
/// have separate deprecation attributes from their parents, so we do not wish to inherit
/// deprecation in this case. For example, inheriting deprecation for `T` in `Foo<T>`
/// would cause a duplicate warning arising from both `Foo` and `T` being deprecated.
#[derive(Clone)]
enum InheritDeprecation {
    Yes,
    No,
}

impl InheritDeprecation {
    fn yes(&self) -> bool {
        matches!(self, InheritDeprecation::Yes)
    }
}

/// Whether to inherit const stability flags for nested items. In most cases, we do not want to
/// inherit const stability: just because an enclosing `fn` is const-stable does not mean
/// all `extern` imports declared in it should be const-stable! However, trait methods
/// inherit const stability attributes from their parent and do not have their own.
enum InheritConstStability {
    Yes,
    No,
}

impl InheritConstStability {
    fn yes(&self) -> bool {
        matches!(self, InheritConstStability::Yes)
    }
}

enum InheritStability {
    Yes,
    No,
}

impl InheritStability {
    fn yes(&self) -> bool {
        matches!(self, InheritStability::Yes)
    }
}

/// A private tree-walker for producing an `Index`.
struct Annotator<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    index: &'a mut Index,
    parent_stab: Option<Stability>,
    parent_const_stab: Option<ConstStability>,
    parent_depr: Option<DeprecationEntry>,
    in_trait_impl: bool,
}

impl<'a, 'tcx> Annotator<'a, 'tcx> {
    /// Determine the stability for a node based on its attributes and inherited stability. The
    /// stability is recorded in the index and used as the parent. If the node is a function,
    /// `fn_sig` is its signature.
    fn annotate<F>(
        &mut self,
        def_id: LocalDefId,
        item_sp: Span,
        fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
        kind: AnnotationKind,
        inherit_deprecation: InheritDeprecation,
        inherit_const_stability: InheritConstStability,
        inherit_from_parent: InheritStability,
        visit_children: F,
    ) where
        F: FnOnce(&mut Self),
    {
        let attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
        debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);

        let depr = attr::find_deprecation(self.tcx.sess, self.tcx.features(), attrs);
        let mut is_deprecated = false;
        if let Some((depr, span)) = &depr {
            is_deprecated = true;

            if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
                let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
                self.tcx.emit_node_span_lint(
                    USELESS_DEPRECATED,
                    hir_id,
                    *span,
                    errors::DeprecatedAnnotationHasNoEffect { span: *span },
                );
            }

            // `Deprecation` is just two pointers, no need to intern it
            let depr_entry = DeprecationEntry::local(*depr, def_id);
            self.index.depr_map.insert(def_id, depr_entry);
        } else if let Some(parent_depr) = self.parent_depr {
            if inherit_deprecation.yes() {
                is_deprecated = true;
                info!("tagging child {:?} as deprecated from parent", def_id);
                self.index.depr_map.insert(def_id, parent_depr);
            }
        }

        if !self.tcx.features().staged_api {
            // Propagate unstability. This can happen even for non-staged-api crates in case
            // -Zforce-unstable-if-unmarked is set.
            if let Some(stab) = self.parent_stab {
                if inherit_deprecation.yes() && stab.is_unstable() {
                    self.index.stab_map.insert(def_id, stab);
                }
            }

            self.recurse_with_stability_attrs(
                depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
                None,
                None,
                visit_children,
            );
            return;
        }

        let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
        let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
        let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
        let mut const_span = None;

        let const_stab = const_stab.map(|(const_stab, const_span_node)| {
            self.index.const_stab_map.insert(def_id, const_stab);
            const_span = Some(const_span_node);
            const_stab
        });

        // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
        // check if the function/method is const or the parent impl block is const
        if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig)
            && fn_sig.header.abi != Abi::RustIntrinsic
            && !fn_sig.header.is_const()
            && (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
        {
            self.tcx
                .dcx()
                .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
        }

        // `impl const Trait for Type` items forward their const stability to their
        // immediate children.
        if const_stab.is_none() {
            debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
            if let Some(parent) = self.parent_const_stab {
                if parent.is_const_unstable() {
                    self.index.const_stab_map.insert(def_id, parent);
                }
            }
        }

        if let Some((depr, span)) = &depr
            && depr.is_since_rustc_version()
            && stab.is_none()
        {
            self.tcx.dcx().emit_err(errors::DeprecatedAttribute { span: *span });
        }

        if let Some((body_stab, _span)) = body_stab {
            // FIXME: check that this item can have body stability

            self.index.default_body_stab_map.insert(def_id, body_stab);
            debug!(?self.index.default_body_stab_map);
        }

        let stab = stab.map(|(stab, span)| {
            // Error if prohibited, or can't inherit anything from a container.
            if kind == AnnotationKind::Prohibited
                || (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
            {
                self.tcx.dcx().emit_err(errors::UselessStability { span, item_sp });
            }

            debug!("annotate: found {:?}", stab);

            // Check if deprecated_since < stable_since. If it is,
            // this is *almost surely* an accident.
            if let (
                &Some(DeprecatedSince::RustcVersion(dep_since)),
                &attr::Stable { since: stab_since, .. },
            ) = (&depr.as_ref().map(|(d, _)| d.since), &stab.level)
            {
                match stab_since {
                    StableSince::Current => {
                        self.tcx
                            .dcx()
                            .emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
                    }
                    StableSince::Version(stab_since) => {
                        if dep_since < stab_since {
                            self.tcx
                                .dcx()
                                .emit_err(errors::CannotStabilizeDeprecated { span, item_sp });
                        }
                    }
                    StableSince::Err => {
                        // An error already reported. Assume the unparseable stabilization
                        // version is older than the deprecation version.
                    }
                }
            }

            if let Stability { level: Unstable { .. }, feature } = stab {
                if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() {
                    self.tcx
                        .dcx()
                        .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp });
                }
            }
            if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } =
                stab
            {
                self.index.implications.insert(implied_by, feature);
            }

            if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab {
                if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() {
                    self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
                        span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span
                        item_sp,
                    });
                }
            }
            if let Some(ConstStability {
                level: Unstable { implied_by: Some(implied_by), .. },
                feature,
                ..
            }) = const_stab
            {
                self.index.implications.insert(implied_by, feature);
            }

            self.index.stab_map.insert(def_id, stab);
            stab
        });

        if stab.is_none() {
            debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
            if let Some(stab) = self.parent_stab {
                if inherit_deprecation.yes() && stab.is_unstable() || inherit_from_parent.yes() {
                    self.index.stab_map.insert(def_id, stab);
                }
            }
        }

        self.recurse_with_stability_attrs(
            depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
            stab,
            inherit_const_stability.yes().then_some(const_stab).flatten(),
            visit_children,
        );
    }

    fn recurse_with_stability_attrs(
        &mut self,
        depr: Option<DeprecationEntry>,
        stab: Option<Stability>,
        const_stab: Option<ConstStability>,
        f: impl FnOnce(&mut Self),
    ) {
        // These will be `Some` if this item changes the corresponding stability attribute.
        let mut replaced_parent_depr = None;
        let mut replaced_parent_stab = None;
        let mut replaced_parent_const_stab = None;

        if let Some(depr) = depr {
            replaced_parent_depr = Some(replace(&mut self.parent_depr, Some(depr)));
        }
        if let Some(stab) = stab {
            replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab)));
        }
        if let Some(const_stab) = const_stab {
            replaced_parent_const_stab =
                Some(replace(&mut self.parent_const_stab, Some(const_stab)));
        }

        f(self);

        if let Some(orig_parent_depr) = replaced_parent_depr {
            self.parent_depr = orig_parent_depr;
        }
        if let Some(orig_parent_stab) = replaced_parent_stab {
            self.parent_stab = orig_parent_stab;
        }
        if let Some(orig_parent_const_stab) = replaced_parent_const_stab {
            self.parent_const_stab = orig_parent_const_stab;
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
    /// Because stability levels are scoped lexically, we want to walk
    /// nested items in the context of the outer item, so enable
    /// deep-walking.
    type NestedFilter = nested_filter::All;

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

    fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
        let orig_in_trait_impl = self.in_trait_impl;
        let mut kind = AnnotationKind::Required;
        let mut const_stab_inherit = InheritConstStability::No;
        let mut fn_sig = None;

        match i.kind {
            // Inherent impls and foreign modules serve only as containers for other items,
            // they don't have their own stability. They still can be annotated as unstable
            // and propagate this instability to children, but this annotation is completely
            // optional. They inherit stability from their parents when unannotated.
            hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
            | hir::ItemKind::ForeignMod { .. } => {
                self.in_trait_impl = false;
                kind = AnnotationKind::Container;
            }
            hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
                self.in_trait_impl = true;
                kind = AnnotationKind::DeprecationProhibited;
                const_stab_inherit = InheritConstStability::Yes;
            }
            hir::ItemKind::Struct(ref sd, _) => {
                if let Some(ctor_def_id) = sd.ctor_def_id() {
                    self.annotate(
                        ctor_def_id,
                        i.span,
                        None,
                        AnnotationKind::Required,
                        InheritDeprecation::Yes,
                        InheritConstStability::No,
                        InheritStability::Yes,
                        |_| {},
                    )
                }
            }
            hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
                fn_sig = Some(item_fn_sig);
            }
            _ => {}
        }

        self.annotate(
            i.owner_id.def_id,
            i.span,
            fn_sig,
            kind,
            InheritDeprecation::Yes,
            const_stab_inherit,
            InheritStability::No,
            |v| intravisit::walk_item(v, i),
        );
        self.in_trait_impl = orig_in_trait_impl;
    }

    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
        let fn_sig = match ti.kind {
            hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
            _ => None,
        };

        self.annotate(
            ti.owner_id.def_id,
            ti.span,
            fn_sig,
            AnnotationKind::Required,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::No,
            |v| {
                intravisit::walk_trait_item(v, ti);
            },
        );
    }

    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
        let kind =
            if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };

        let fn_sig = match ii.kind {
            hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
            _ => None,
        };

        self.annotate(
            ii.owner_id.def_id,
            ii.span,
            fn_sig,
            kind,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::No,
            |v| {
                intravisit::walk_impl_item(v, ii);
            },
        );
    }

    fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
        self.annotate(
            var.def_id,
            var.span,
            None,
            AnnotationKind::Required,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::Yes,
            |v| {
                if let Some(ctor_def_id) = var.data.ctor_def_id() {
                    v.annotate(
                        ctor_def_id,
                        var.span,
                        None,
                        AnnotationKind::Required,
                        InheritDeprecation::Yes,
                        InheritConstStability::No,
                        InheritStability::Yes,
                        |_| {},
                    );
                }

                intravisit::walk_variant(v, var)
            },
        )
    }

    fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
        self.annotate(
            s.def_id,
            s.span,
            None,
            AnnotationKind::Required,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::Yes,
            |v| {
                intravisit::walk_field_def(v, s);
            },
        );
    }

    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
        self.annotate(
            i.owner_id.def_id,
            i.span,
            None,
            AnnotationKind::Required,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::No,
            |v| {
                intravisit::walk_foreign_item(v, i);
            },
        );
    }

    fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
        let kind = match &p.kind {
            // Allow stability attributes on default generic arguments.
            hir::GenericParamKind::Type { default: Some(_), .. }
            | hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container,
            _ => AnnotationKind::Prohibited,
        };

        self.annotate(
            p.def_id,
            p.span,
            None,
            kind,
            InheritDeprecation::No,
            InheritConstStability::No,
            InheritStability::No,
            |v| {
                intravisit::walk_generic_param(v, p);
            },
        );
    }
}

struct MissingStabilityAnnotations<'tcx> {
    tcx: TyCtxt<'tcx>,
    effective_visibilities: &'tcx EffectiveVisibilities,
}

impl<'tcx> MissingStabilityAnnotations<'tcx> {
    fn check_missing_stability(&self, def_id: LocalDefId, span: Span) {
        let stab = self.tcx.stability().local_stability(def_id);
        if !self.tcx.sess.is_test_crate()
            && stab.is_none()
            && self.effective_visibilities.is_reachable(def_id)
        {
            let descr = self.tcx.def_descr(def_id.to_def_id());
            self.tcx.dcx().emit_err(errors::MissingStabilityAttr { span, descr });
        }
    }

    fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
        if !self.tcx.features().staged_api {
            return;
        }

        // if the const impl is derived using the `derive_const` attribute,
        // then it would be "stable" at least for the impl.
        // We gate usages of it using `feature(const_trait_impl)` anyways
        // so there is no unstable leakage
        if self.tcx.is_automatically_derived(def_id.to_def_id()) {
            return;
        }

        let is_const = self.tcx.is_const_fn(def_id.to_def_id())
            || self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
        let is_stable =
            self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
        let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();

        if is_const && is_stable && missing_const_stability_attribute {
            let descr = self.tcx.def_descr(def_id.to_def_id());
            self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr });
        }
    }
}

impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
    type NestedFilter = nested_filter::OnlyBodies;

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

    fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
        // Inherent impls and foreign modules serve only as containers for other items,
        // they don't have their own stability. They still can be annotated as unstable
        // and propagate this instability to children, but this annotation is completely
        // optional. They inherit stability from their parents when unannotated.
        if !matches!(
            i.kind,
            hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
                | hir::ItemKind::ForeignMod { .. }
        ) {
            self.check_missing_stability(i.owner_id.def_id, i.span);
        }

        // Ensure stable `const fn` have a const stability attribute.
        self.check_missing_const_stability(i.owner_id.def_id, i.span);

        intravisit::walk_item(self, i)
    }

    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
        self.check_missing_stability(ti.owner_id.def_id, ti.span);
        intravisit::walk_trait_item(self, ti);
    }

    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
        let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
        if self.tcx.impl_trait_ref(impl_def_id).is_none() {
            self.check_missing_stability(ii.owner_id.def_id, ii.span);
            self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
        }
        intravisit::walk_impl_item(self, ii);
    }

    fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
        self.check_missing_stability(var.def_id, var.span);
        if let Some(ctor_def_id) = var.data.ctor_def_id() {
            self.check_missing_stability(ctor_def_id, var.span);
        }
        intravisit::walk_variant(self, var);
    }

    fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
        self.check_missing_stability(s.def_id, s.span);
        intravisit::walk_field_def(self, s);
    }

    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
        self.check_missing_stability(i.owner_id.def_id, i.span);
        intravisit::walk_foreign_item(self, i);
    }
    // Note that we don't need to `check_missing_stability` for default generic parameters,
    // as we assume that any default generic parameters without attributes are automatically
    // stable (assuming they have not inherited instability from their parent).
}

fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
    let mut index = Index {
        stab_map: Default::default(),
        const_stab_map: Default::default(),
        default_body_stab_map: Default::default(),
        depr_map: Default::default(),
        implications: Default::default(),
    };

    {
        let mut annotator = Annotator {
            tcx,
            index: &mut index,
            parent_stab: None,
            parent_const_stab: None,
            parent_depr: None,
            in_trait_impl: false,
        };

        // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
        // a parent stability annotation which indicates that this is private
        // with the `rustc_private` feature. This is intended for use when
        // compiling `librustc_*` crates themselves so we can leverage crates.io
        // while maintaining the invariant that all sysroot crates are unstable
        // by default and are unable to be used.
        if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
            let stability = Stability {
                level: attr::StabilityLevel::Unstable {
                    reason: UnstableReason::Default,
                    issue: NonZero::new(27812),
                    is_soft: false,
                    implied_by: None,
                },
                feature: sym::rustc_private,
            };
            annotator.parent_stab = Some(stability);
        }

        annotator.annotate(
            CRATE_DEF_ID,
            tcx.hir().span(CRATE_HIR_ID),
            None,
            AnnotationKind::Required,
            InheritDeprecation::Yes,
            InheritConstStability::No,
            InheritStability::No,
            |v| tcx.hir().walk_toplevel_module(v),
        );
    }
    index
}

/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
    tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
}

pub(crate) fn provide(providers: &mut Providers) {
    *providers = Providers {
        check_mod_unstable_api_usage,
        stability_index,
        stability_implications: |tcx, _| tcx.stability().implications.clone(),
        lookup_stability: |tcx, id| tcx.stability().local_stability(id),
        lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id),
        lookup_default_body_stability: |tcx, id| tcx.stability().local_default_body_stability(id),
        lookup_deprecation_entry: |tcx, id| tcx.stability().local_deprecation_entry(id),
        ..*providers
    };
}

struct Checker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
    type NestedFilter = nested_filter::OnlyBodies;

    /// Because stability levels are scoped lexically, we want to walk
    /// nested items in the context of the outer item, so enable
    /// deep-walking.
    fn nested_visit_map(&mut self) -> Self::Map {
        self.tcx.hir()
    }

    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
        match item.kind {
            hir::ItemKind::ExternCrate(_) => {
                // compiler-generated `extern crate` items have a dummy span.
                // `std` is still checked for the `restricted-std` feature.
                if item.span.is_dummy() && item.ident.name != sym::std {
                    return;
                }

                let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.owner_id.def_id) else {
                    return;
                };
                let def_id = cnum.as_def_id();
                self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None);
            }

            // For implementations of traits, check the stability of each item
            // individually as it's possible to have a stable trait with unstable
            // items.
            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
                let features = self.tcx.features();
                if features.staged_api {
                    let attrs = self.tcx.hir().attrs(item.hir_id());
                    let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
                    let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);

                    // If this impl block has an #[unstable] attribute, give an
                    // error if all involved types and traits are stable, because
                    // it will have no effect.
                    // See: https://github.com/rust-lang/rust/issues/55436
                    if let Some((Stability { level: attr::Unstable { .. }, .. }, span)) = stab {
                        let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
                        c.visit_ty(self_ty);
                        c.visit_trait_ref(t);

                        // do not lint when the trait isn't resolved, since resolution error should
                        // be fixed first
                        if t.path.res != Res::Err && c.fully_stable {
                            self.tcx.emit_node_span_lint(
                                INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
                                item.hir_id(),
                                span,
                                errors::IneffectiveUnstableImpl,
                            );
                        }
                    }

                    // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
                    // needs to have an error emitted.
                    if features.const_trait_impl
                        && self.tcx.is_const_trait_impl_raw(item.owner_id.to_def_id())
                        && const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
                    {
                        self.tcx.dcx().emit_err(errors::TraitImplConstStable { span: item.span });
                    }
                }

                for impl_item_ref in *items {
                    let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id);

                    if let Some(def_id) = impl_item.trait_item_def_id {
                        // Pass `None` to skip deprecation warnings.
                        self.tcx.check_stability(def_id, None, impl_item_ref.span, None);
                    }
                }
            }

            _ => (/* pass */),
        }
        intravisit::walk_item(self, item);
    }

    fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) {
        if let Some(def_id) = path.res.opt_def_id() {
            let method_span = path.segments.last().map(|s| s.ident.span);
            let item_is_allowed = self.tcx.check_stability_allow_unstable(
                def_id,
                Some(id),
                path.span,
                method_span,
                if is_unstable_reexport(self.tcx, id) {
                    AllowUnstable::Yes
                } else {
                    AllowUnstable::No
                },
            );

            let is_allowed_through_unstable_modules = |def_id| {
                self.tcx.lookup_stability(def_id).is_some_and(|stab| match stab.level {
                    StabilityLevel::Stable { allowed_through_unstable_modules, .. } => {
                        allowed_through_unstable_modules
                    }
                    _ => false,
                })
            };

            if item_is_allowed && !is_allowed_through_unstable_modules(def_id) {
                // Check parent modules stability as well if the item the path refers to is itself
                // stable. We only emit warnings for unstable path segments if the item is stable
                // or allowed because stability is often inherited, so the most common case is that
                // both the segments and the item are unstable behind the same feature flag.
                //
                // We check here rather than in `visit_path_segment` to prevent visiting the last
                // path segment twice
                //
                // We include special cases via #[rustc_allowed_through_unstable_modules] for items
                // that were accidentally stabilized through unstable paths before this check was
                // added, such as `core::intrinsics::transmute`
                let parents = path.segments.iter().rev().skip(1);
                for path_segment in parents {
                    if let Some(def_id) = path_segment.res.opt_def_id() {
                        // use `None` for id to prevent deprecation check
                        self.tcx.check_stability_allow_unstable(
                            def_id,
                            None,
                            path.span,
                            None,
                            if is_unstable_reexport(self.tcx, id) {
                                AllowUnstable::Yes
                            } else {
                                AllowUnstable::No
                            },
                        );
                    }
                }
            }
        }

        intravisit::walk_path(self, path)
    }
}

/// Check whether a path is a `use` item that has been marked as unstable.
///
/// See issue #94972 for details on why this is a special case
fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
    // Get the LocalDefId so we can lookup the item to check the kind.
    let Some(owner) = id.as_owner() else {
        return false;
    };
    let def_id = owner.def_id;

    let Some(stab) = tcx.stability().local_stability(def_id) else {
        return false;
    };

    if stab.level.is_stable() {
        // The re-export is not marked as unstable, don't override
        return false;
    }

    // If this is a path that isn't a use, we don't need to do anything special
    if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) {
        return false;
    }

    true
}

struct CheckTraitImplStable<'tcx> {
    tcx: TyCtxt<'tcx>,
    fully_stable: bool,
}

impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
    fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: hir::HirId) {
        if let Some(def_id) = path.res.opt_def_id() {
            if let Some(stab) = self.tcx.lookup_stability(def_id) {
                self.fully_stable &= stab.level.is_stable();
            }
        }
        intravisit::walk_path(self, path)
    }

    fn visit_trait_ref(&mut self, t: &'tcx TraitRef<'tcx>) {
        if let Res::Def(DefKind::Trait, trait_did) = t.path.res {
            if let Some(stab) = self.tcx.lookup_stability(trait_did) {
                self.fully_stable &= stab.level.is_stable();
            }
        }
        intravisit::walk_trait_ref(self, t)
    }

    fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
        if let TyKind::Never = t.kind {
            self.fully_stable = false;
        }
        if let TyKind::BareFn(f) = t.kind {
            if rustc_target::spec::abi::is_stable(f.abi.name()).is_err() {
                self.fully_stable = false;
            }
        }
        intravisit::walk_ty(self, t)
    }

    fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
        for ty in fd.inputs {
            self.visit_ty(ty)
        }
        if let hir::FnRetTy::Return(output_ty) = fd.output {
            match output_ty.kind {
                TyKind::Never => {} // `-> !` is stable
                _ => self.visit_ty(output_ty),
            }
        }
    }
}

/// Given the list of enabled features that were not language features (i.e., that
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
    let is_staged_api =
        tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api;
    if is_staged_api {
        let effective_visibilities = &tcx.effective_visibilities(());
        let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
        missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
        tcx.hir().walk_toplevel_module(&mut missing);
        tcx.hir().visit_all_item_likes_in_crate(&mut missing);
    }

    let declared_lang_features = &tcx.features().declared_lang_features;
    let mut lang_features = UnordSet::default();
    for &(feature, span, since) in declared_lang_features {
        if let Some(since) = since {
            // Warn if the user has enabled an already-stable lang feature.
            unnecessary_stable_feature_lint(tcx, span, feature, since);
        }
        if !lang_features.insert(feature) {
            // Warn if the user enables a lang feature multiple times.
            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span, feature });
        }
    }

    let declared_lib_features = &tcx.features().declared_lib_features;
    let mut remaining_lib_features = FxIndexMap::default();
    for (feature, span) in declared_lib_features {
        if remaining_lib_features.contains_key(&feature) {
            // Warn if the user enables a lib feature multiple times.
            tcx.dcx().emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
        }
        remaining_lib_features.insert(feature, *span);
    }
    // `stdbuild` has special handling for `libc`, so we need to
    // recognise the feature when building std.
    // Likewise, libtest is handled specially, so `test` isn't
    // available as we'd like it to be.
    // FIXME: only remove `libc` when `stdbuild` is active.
    // FIXME: remove special casing for `test`.
    // FIXME(#120456) - is `swap_remove` correct?
    remaining_lib_features.swap_remove(&sym::libc);
    remaining_lib_features.swap_remove(&sym::test);

    /// For each feature in `defined_features`..
    ///
    /// - If it is in `remaining_lib_features` (those features with `#![feature(..)]` attributes in
    ///   the current crate), check if it is stable (or partially stable) and thus an unnecessary
    ///   attribute.
    /// - If it is in `remaining_implications` (a feature that is referenced by an `implied_by`
    ///   from the current crate), then remove it from the remaining implications.
    ///
    /// Once this function has been invoked for every feature (local crate and all extern crates),
    /// then..
    ///
    /// - If features remain in `remaining_lib_features`, then the user has enabled a feature that
    ///   does not exist.
    /// - If features remain in `remaining_implications`, the `implied_by` refers to a feature that
    ///   does not exist.
    ///
    /// By structuring the code in this way: checking the features defined from each crate one at a
    /// time, less loading from metadata is performed and thus compiler performance is improved.
    fn check_features<'tcx>(
        tcx: TyCtxt<'tcx>,
        remaining_lib_features: &mut FxIndexMap<&Symbol, Span>,
        remaining_implications: &mut UnordMap<Symbol, Symbol>,
        defined_features: &LibFeatures,
        all_implications: &UnordMap<Symbol, Symbol>,
    ) {
        for (feature, since) in defined_features.to_sorted_vec() {
            if let FeatureStability::AcceptedSince(since) = since
                && let Some(span) = remaining_lib_features.get(&feature)
            {
                // Warn if the user has enabled an already-stable lib feature.
                if let Some(implies) = all_implications.get(&feature) {
                    unnecessary_partially_stable_feature_lint(tcx, *span, feature, *implies, since);
                } else {
                    unnecessary_stable_feature_lint(tcx, *span, feature, since);
                }
            }
            // FIXME(#120456) - is `swap_remove` correct?
            remaining_lib_features.swap_remove(&feature);

            // `feature` is the feature doing the implying, but `implied_by` is the feature with
            // the attribute that establishes this relationship. `implied_by` is guaranteed to be a
            // feature defined in the local crate because `remaining_implications` is only the
            // implications from this crate.
            remaining_implications.remove(&feature);

            if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
                break;
            }
        }
    }

    // All local crate implications need to have the feature that implies it confirmed to exist.
    let mut remaining_implications = tcx.stability_implications(LOCAL_CRATE).clone();

    // We always collect the lib features declared in the current crate, even if there are
    // no unknown features, because the collection also does feature attribute validation.
    let local_defined_features = tcx.lib_features(LOCAL_CRATE);
    if !remaining_lib_features.is_empty() || !remaining_implications.is_empty() {
        // Loading the implications of all crates is unavoidable to be able to emit the partial
        // stabilization diagnostic, but it can be avoided when there are no
        // `remaining_lib_features`.
        let mut all_implications = remaining_implications.clone();
        for &cnum in tcx.crates(()) {
            all_implications
                .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v)));
        }

        check_features(
            tcx,
            &mut remaining_lib_features,
            &mut remaining_implications,
            local_defined_features,
            &all_implications,
        );

        for &cnum in tcx.crates(()) {
            if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
                break;
            }
            check_features(
                tcx,
                &mut remaining_lib_features,
                &mut remaining_implications,
                tcx.lib_features(cnum),
                &all_implications,
            );
        }
    }

    for (feature, span) in remaining_lib_features {
        tcx.dcx().emit_err(errors::UnknownFeature { span, feature: *feature });
    }

    for (&implied_by, &feature) in remaining_implications.to_sorted_stable_ord() {
        let local_defined_features = tcx.lib_features(LOCAL_CRATE);
        let span = local_defined_features
            .stability
            .get(&feature)
            .expect("feature that implied another does not exist")
            .1;
        tcx.dcx().emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
    }

    // FIXME(#44232): the `used_features` table no longer exists, so we
    // don't lint about unused features. We should re-enable this one day!
}

fn unnecessary_partially_stable_feature_lint(
    tcx: TyCtxt<'_>,
    span: Span,
    feature: Symbol,
    implies: Symbol,
    since: Symbol,
) {
    tcx.emit_node_span_lint(
        lint::builtin::STABLE_FEATURES,
        hir::CRATE_HIR_ID,
        span,
        errors::UnnecessaryPartialStableFeature {
            span,
            line: tcx.sess.source_map().span_extend_to_line(span),
            feature,
            since,
            implies,
        },
    );
}

fn unnecessary_stable_feature_lint(
    tcx: TyCtxt<'_>,
    span: Span,
    feature: Symbol,
    mut since: Symbol,
) {
    if since.as_str() == VERSION_PLACEHOLDER {
        since = sym::env_CFG_RELEASE;
    }
    tcx.emit_node_span_lint(
        lint::builtin::STABLE_FEATURES,
        hir::CRATE_HIR_ID,
        span,
        errors::UnnecessaryStableFeature { feature, since },
    );
}
