//! Support for inlining external documentation into the current AST.

use std::iter::once;
use std::sync::Arc;

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
use rustc_hir::def::{DefKind, MacroKinds, Res};
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
use rustc_hir::{self as hir, Mutability, find_attr};
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{Symbol, sym};
use tracing::{debug, trace};

use super::{Item, extract_cfg_from_attrs};
use crate::clean::{
    self, Attributes, CfgInfo, ImplKind, ItemId, Type, clean_bound_vars, clean_generics,
    clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty,
    clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type,
    clean_ty_generics, clean_variant_def, utils,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;

/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition specified, and if it is
/// from another crate it will attempt to inline the documentation
/// from the other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the definition could not be inlined,
/// and `Some` of a vector of items if it was successfully expanded.
pub(crate) fn try_inline(
    cx: &mut DocContext<'_>,
    res: Res,
    name: Symbol,
    attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
    visited: &mut DefIdSet,
) -> Option<Vec<clean::Item>> {
    fn try_inline_inner(
        cx: &mut DocContext<'_>,
        kind: clean::ItemKind,
        did: DefId,
        name: Symbol,
        import_def_id: Option<LocalDefId>,
    ) -> clean::Item {
        cx.inlined.insert(did.into());
        let mut item = crate::clean::generate_item_with_correct_attrs(
            cx,
            kind,
            did,
            name,
            import_def_id.as_slice(),
            None,
        );
        // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
        item.inner.inline_stmt_id = import_def_id;
        item
    }

    let did = res.opt_def_id()?;
    if did.is_local() {
        return None;
    }
    let mut ret = Vec::new();

    debug!("attrs={attrs:?}");

    let attrs_without_docs = attrs.map(|(attrs, def_id)| {
        (attrs.iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
    });
    let attrs_without_docs =
        attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));

    let import_def_id = attrs.and_then(|(_, def_id)| def_id);

    let kind = match res {
        Res::Def(DefKind::Trait, did) => {
            record_extern_fqn(cx, did, ItemType::Trait);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::TraitItem(Box::new(build_trait(cx, did)))
            })
        }
        Res::Def(DefKind::TraitAlias, did) => {
            record_extern_fqn(cx, did, ItemType::TraitAlias);
            cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did)))
        }
        Res::Def(DefKind::Fn, did) => {
            record_extern_fqn(cx, did, ItemType::Function);
            cx.with_param_env(did, |cx| {
                clean::enter_impl_trait(cx, |cx| clean::FunctionItem(build_function(cx, did)))
            })
        }
        Res::Def(DefKind::Struct, did) => {
            record_extern_fqn(cx, did, ItemType::Struct);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::StructItem(build_struct(cx, did))
            })
        }
        Res::Def(DefKind::Union, did) => {
            record_extern_fqn(cx, did, ItemType::Union);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::UnionItem(build_union(cx, did))
            })
        }
        Res::Def(DefKind::TyAlias, did) => {
            record_extern_fqn(cx, did, ItemType::TypeAlias);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::TypeAliasItem(build_type_alias(cx, did, &mut ret))
            })
        }
        Res::Def(DefKind::Enum, did) => {
            record_extern_fqn(cx, did, ItemType::Enum);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::EnumItem(build_enum(cx, did))
            })
        }
        Res::Def(DefKind::ForeignTy, did) => {
            record_extern_fqn(cx, did, ItemType::ForeignType);
            cx.with_param_env(did, |cx| {
                build_impls(cx, did, attrs_without_docs, &mut ret);
                clean::ForeignTypeItem
            })
        }
        // Never inline enum variants but leave them shown as re-exports.
        Res::Def(DefKind::Variant, _) => return None,
        // Assume that enum variants and struct types are re-exported next to
        // their constructors.
        Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()),
        Res::Def(DefKind::Mod, did) => {
            record_extern_fqn(cx, did, ItemType::Module);
            clean::ModuleItem(build_module(cx, did, name, visited))
        }
        Res::Def(DefKind::Static { .. }, did) => {
            record_extern_fqn(cx, did, ItemType::Static);
            cx.with_param_env(did, |cx| {
                clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
            })
        }
        Res::Def(DefKind::Const { .. }, did) => {
            record_extern_fqn(cx, did, ItemType::Constant);
            cx.with_param_env(did, |cx| {
                let ct = build_const_item(cx, did);
                clean::ConstantItem(Box::new(ct))
            })
        }
        Res::Def(DefKind::Macro(kinds), did) => {
            let mac = build_macro(cx.tcx, did, name, kinds);

            let type_kind = match kinds {
                MacroKinds::BANG => ItemType::Macro,
                MacroKinds::ATTR => ItemType::ProcAttribute,
                MacroKinds::DERIVE => ItemType::ProcDerive,
                // Then it means it's more than one type so we default to "macro".
                _ => ItemType::Macro,
            };
            record_extern_fqn(cx, did, type_kind);
            ret.push(try_inline_inner(cx, mac, did, name, import_def_id));
            return Some(ret);
        }
        _ => return None,
    };

    ret.push(try_inline_inner(cx, kind, did, name, import_def_id));
    Some(ret)
}

pub(crate) fn try_inline_glob(
    cx: &mut DocContext<'_>,
    res: Res,
    current_mod: LocalModDefId,
    visited: &mut DefIdSet,
    inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
    import: &hir::Item<'_>,
) -> Option<Vec<clean::Item>> {
    let did = res.opt_def_id()?;
    if did.is_local() {
        return None;
    }

    match res {
        Res::Def(DefKind::Mod, did) => {
            // Use the set of module reexports to filter away names that are not actually
            // reexported by the glob, e.g. because they are shadowed by something else.
            let reexports = cx
                .tcx
                .module_children_local(current_mod.to_local_def_id())
                .iter()
                .filter(|child| !child.reexport_chain.is_empty())
                .filter_map(|child| child.res.opt_def_id())
                .filter(|&def_id| !cx.tcx.is_doc_hidden(def_id))
                .collect();
            let attrs = cx.tcx.hir_attrs(import.hir_id());
            let mut items = build_module_items(
                cx,
                did,
                cx.tcx.item_name(did),
                visited,
                inlined_names,
                Some(&reexports),
                Some((attrs, Some(import.owner_id.def_id))),
            );
            items.retain(|item| {
                if let Some(name) = item.name {
                    // If an item with the same type and name already exists,
                    // it takes priority over the inlined stuff.
                    inlined_names.insert((item.type_(), name))
                } else {
                    true
                }
            });
            Some(items)
        }
        // glob imports on things like enums aren't inlined even for local exports, so just bail
        _ => None,
    }
}

pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [hir::Attribute] {
    // FIXME: all uses should use `find_attr`!
    #[allow(deprecated)]
    tcx.get_all_attrs(did)
}

pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
    tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect()
}

/// Get the public Rust path to an item. This is used to generate the URL to the item's page.
///
/// In particular: we handle macro differently: if it's not a macro 2.0 oe a built-in macro, then
/// it is generated at the top-level of the crate and its path will be `[crate_name, macro_name]`.
pub(crate) fn get_item_path(tcx: TyCtxt<'_>, def_id: DefId, kind: ItemType) -> Vec<Symbol> {
    let crate_name = tcx.crate_name(def_id.krate);
    let relative = item_relative_path(tcx, def_id);

    if let ItemType::Macro = kind {
        // Check to see if it is a macro 2.0 or built-in macro
        // More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
        if matches!(
            CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id),
            LoadedMacro::MacroDef { def, .. } if !def.macro_rules
        ) {
            once(crate_name).chain(relative).collect()
        } else {
            vec![crate_name, *relative.last().expect("relative was empty")]
        }
    } else {
        once(crate_name).chain(relative).collect()
    }
}

/// Record an external fully qualified name in the external_paths cache.
///
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
    if did.is_local() {
        if cx.cache.exact_paths.contains_key(&did) {
            return;
        }
    } else if cx.cache.external_paths.contains_key(&did) {
        return;
    }

    let item_path = get_item_path(cx.tcx, did, kind);

    if did.is_local() {
        cx.cache.exact_paths.insert(did, item_path);
    } else {
        cx.cache.external_paths.insert(did, (item_path, kind));
    }
}

pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
    let trait_items = cx
        .tcx
        .associated_items(did)
        .in_definition_order()
        .filter(|item| !item.is_impl_trait_in_trait())
        .map(|item| clean_middle_assoc_item(item, cx))
        .collect();

    let generics = clean_ty_generics(cx, did);
    let (generics, mut supertrait_bounds) = separate_self_bounds(generics);

    supertrait_bounds.retain(|b| {
        // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
        // is shown and none of the new sizedness traits leak into documentation.
        !b.is_meta_sized_bound(cx.tcx)
    });

    clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
}

fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
    let generics = clean_ty_generics(cx, did);
    let (generics, mut bounds) = separate_self_bounds(generics);

    bounds.retain(|b| {
        // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
        // is shown and none of the new sizedness traits leak into documentation.
        !b.is_meta_sized_bound(cx.tcx)
    });

    clean::TraitAlias { generics, bounds }
}

pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
    let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
    // The generics need to be cleaned before the signature.
    let mut generics = clean_ty_generics(cx, def_id);
    let bound_vars = clean_bound_vars(sig.bound_vars(), cx.tcx);

    // At the time of writing early & late-bound params are stored separately in rustc,
    // namely in `generics.params` and `bound_vars` respectively.
    //
    // To reestablish the original source code order of the generic parameters, we
    // need to manually sort them by their definition span after concatenation.
    //
    // See also:
    // * https://rustc-dev-guide.rust-lang.org/bound-vars-and-params.html
    // * https://rustc-dev-guide.rust-lang.org/what-does-early-late-bound-mean.html
    let has_early_bound_params = !generics.params.is_empty();
    let has_late_bound_params = !bound_vars.is_empty();
    generics.params.extend(bound_vars);
    if has_early_bound_params && has_late_bound_params {
        // If this ever becomes a performances bottleneck either due to the sorting
        // or due to the query calls, consider inserting the late-bound lifetime params
        // right after the last early-bound lifetime param followed by only sorting
        // the slice of lifetime params.
        generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap());
    }

    let decl = clean_poly_fn_sig(cx, Some(def_id), sig);

    Box::new(clean::Function { decl, generics })
}

fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
    clean::Enum {
        generics: clean_ty_generics(cx, did),
        variants: cx.tcx.adt_def(did).variants().iter().map(|v| clean_variant_def(v, cx)).collect(),
    }
}

fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
    let variant = cx.tcx.adt_def(did).non_enum_variant();

    clean::Struct {
        ctor_kind: variant.ctor_kind(),
        generics: clean_ty_generics(cx, did),
        fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
    }
}

fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
    let variant = cx.tcx.adt_def(did).non_enum_variant();

    let generics = clean_ty_generics(cx, did);
    let fields = variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect();
    clean::Union { generics, fields }
}

fn build_type_alias(
    cx: &mut DocContext<'_>,
    did: DefId,
    ret: &mut Vec<Item>,
) -> Box<clean::TypeAlias> {
    let ty = cx.tcx.type_of(did).instantiate_identity().skip_norm_wip();
    let type_ = clean_middle_ty(ty::Binder::dummy(ty), cx, Some(did), None);
    let inner_type = clean_ty_alias_inner_type(ty, cx, ret);

    Box::new(clean::TypeAlias {
        type_,
        generics: clean_ty_generics(cx, did),
        inner_type,
        item_type: None,
    })
}

/// Builds all inherent implementations of an ADT (struct/union/enum) or Trait item/path/reexport.
pub(crate) fn build_impls(
    cx: &mut DocContext<'_>,
    did: DefId,
    attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
    ret: &mut Vec<clean::Item>,
) {
    let tcx = cx.tcx;
    let _prof_timer = tcx.sess.prof.generic_activity("build_inherent_impls");

    // for each implementation of an item represented by `did`, build the clean::Item for that impl
    for &did in tcx.inherent_impls(did).iter() {
        cx.with_param_env(did, |cx| {
            build_impl(cx, did, attrs, ret);
        });
    }

    // This pretty much exists expressly for `dyn Error` traits that exist in the `alloc` crate.
    // See also:
    //
    // * https://github.com/rust-lang/rust/issues/103170 — where it didn't used to get documented
    // * https://github.com/rust-lang/rust/pull/99917 — where the feature got used
    // * https://github.com/rust-lang/rust/issues/53487 — overall tracking issue for Error
    if find_attr!(tcx, did, RustcHasIncoherentInherentImpls) {
        let type_ =
            if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
        for &did in tcx.incoherent_impls(type_).iter() {
            cx.with_param_env(did, |cx| {
                build_impl(cx, did, attrs, ret);
            });
        }
    }
}

pub(crate) fn merge_attrs(
    tcx: TyCtxt<'_>,
    old_attrs: &[hir::Attribute],
    new_attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
    cfg_info: &mut CfgInfo,
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
    // NOTE: If we have additional attributes (from a re-export),
    // always insert them first. This ensure that re-export
    // doc comments show up before the original doc comments
    // when we render them.
    if let Some((inner, item_id)) = new_attrs {
        let mut both = inner.to_vec();
        both.extend_from_slice(old_attrs);
        (
            if let Some(item_id) = item_id {
                Attributes::from_hir_with_additional(old_attrs, (inner, item_id.to_def_id()))
            } else {
                Attributes::from_hir(&both)
            },
            extract_cfg_from_attrs(both.iter(), tcx, cfg_info),
        )
    } else {
        (Attributes::from_hir(old_attrs), extract_cfg_from_attrs(old_attrs.iter(), tcx, cfg_info))
    }
}

/// Inline an `impl`, inherent or of a trait. The `did` must be for an `impl`.
pub(crate) fn build_impl(
    cx: &mut DocContext<'_>,
    did: DefId,
    attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
    ret: &mut Vec<clean::Item>,
) {
    if !cx.inlined.insert(did.into()) {
        return;
    }

    let tcx = cx.tcx;
    let _prof_timer = tcx.sess.prof.generic_activity("build_impl");

    let associated_trait = tcx.impl_opt_trait_ref(did).map(ty::EarlyBinder::skip_binder);

    // Do not inline compiler-internal items unless we're a compiler-internal crate.
    let is_compiler_internal = |did| {
        tcx.lookup_stability(did)
            .is_some_and(|stab| stab.is_unstable() && stab.feature == sym::rustc_private)
    };
    let document_compiler_internal = is_compiler_internal(LOCAL_CRATE.as_def_id());
    let is_directly_public = |cx: &mut DocContext<'_>, did| {
        cx.cache.effective_visibilities.is_directly_public(tcx, did)
            && (document_compiler_internal || !is_compiler_internal(did))
    };

    // Only inline impl if the implemented trait is
    // reachable in rustdoc generated documentation
    if !did.is_local()
        && let Some(traitref) = associated_trait
        && !is_directly_public(cx, traitref.def_id)
    {
        return;
    }

    let impl_item = match did.as_local() {
        Some(did) => match &tcx.hir_expect_item(did).kind {
            hir::ItemKind::Impl(impl_) => Some(impl_),
            _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
        },
        None => None,
    };

    let for_ = match &impl_item {
        Some(impl_) => clean_ty(impl_.self_ty, cx),
        None => clean_middle_ty(
            ty::Binder::dummy(tcx.type_of(did).instantiate_identity().skip_norm_wip()),
            cx,
            Some(did),
            None,
        ),
    };

    // Only inline impl if the implementing type is
    // reachable in rustdoc generated documentation
    if !did.is_local()
        && let Some(did) = for_.def_id(&cx.cache)
        && !is_directly_public(cx, did)
    {
        return;
    }

    let document_hidden = cx.document_hidden();
    let (trait_items, generics) = match impl_item {
        Some(impl_) => (
            impl_
                .items
                .iter()
                .map(|&item| tcx.hir_impl_item(item))
                .filter(|item| {
                    // Filter out impl items whose corresponding trait item has `doc(hidden)`
                    // not to document such impl items.
                    // For inherent impls, we don't do any filtering, because that's already done in strip_hidden.rs.

                    // When `--document-hidden-items` is passed, we don't
                    // do any filtering, too.
                    if document_hidden {
                        return true;
                    }
                    if let Some(associated_trait) = associated_trait {
                        let assoc_tag = match item.kind {
                            hir::ImplItemKind::Const(..) => ty::AssocTag::Const,
                            hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn,
                            hir::ImplItemKind::Type(..) => ty::AssocTag::Type,
                        };
                        let trait_item = tcx
                            .associated_items(associated_trait.def_id)
                            .find_by_ident_and_kind(
                                tcx,
                                item.ident,
                                assoc_tag,
                                associated_trait.def_id,
                            )
                            .unwrap(); // SAFETY: For all impl items there exists trait item that has the same name.
                        !tcx.is_doc_hidden(trait_item.def_id)
                    } else {
                        true
                    }
                })
                .map(|item| clean_impl_item(item, cx))
                .collect::<Vec<_>>(),
            clean_generics(impl_.generics, cx),
        ),
        None => (
            tcx.associated_items(did)
                .in_definition_order()
                .filter(|item| !item.is_impl_trait_in_trait())
                .filter(|item| {
                    // If this is a trait impl, filter out associated items whose corresponding item
                    // in the associated trait is marked `doc(hidden)`.
                    // If this is an inherent impl, filter out private associated items.
                    if let Some(associated_trait) = associated_trait {
                        let trait_item = tcx
                            .associated_items(associated_trait.def_id)
                            .find_by_ident_and_kind(
                                tcx,
                                item.ident(tcx),
                                item.tag(),
                                associated_trait.def_id,
                            )
                            .unwrap(); // corresponding associated item has to exist
                        document_hidden || !tcx.is_doc_hidden(trait_item.def_id)
                    } else {
                        item.visibility(tcx).is_public()
                    }
                })
                .map(|item| clean_middle_assoc_item(item, cx))
                .collect::<Vec<_>>(),
            clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)),
        ),
    };
    let polarity = if associated_trait.is_some() {
        tcx.impl_polarity(did)
    } else {
        ty::ImplPolarity::Positive
    };
    let trait_ = associated_trait
        .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
    if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
        && polarity != ty::ImplPolarity::Negative
    {
        super::build_deref_target_impls(cx, &trait_items, ret);
    }

    if !document_hidden {
        // Return if the trait itself or any types of the generic parameters are doc(hidden).
        let mut stack: Vec<&Type> = vec![&for_];

        if let Some(did) = trait_.as_ref().map(|t| t.def_id())
            && tcx.is_doc_hidden(did)
        {
            return;
        }

        if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
            stack.extend(generics);
        }

        while let Some(ty) = stack.pop() {
            if let Some(did) = ty.def_id(&cx.cache)
                && tcx.is_doc_hidden(did)
            {
                return;
            }
            if let Some(generics) = ty.generics() {
                stack.extend(generics);
            }
        }
    }

    if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
        cx.with_param_env(did, |cx| {
            record_extern_trait(cx, did);
        });
    }

    // In here, we pass an empty `CfgInfo` because the computation of `cfg` happens later, so it
    // doesn't matter at this point.
    //
    // We need to pass this empty `CfgInfo` because `merge_attrs` is used when computing the `cfg`.
    let (merged_attrs, cfg) =
        merge_attrs(cx.tcx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default());
    trace!("merged_attrs={merged_attrs:?}");

    trace!(
        "build_impl: impl {:?} for {:?}",
        trait_.as_ref().map(|t| t.def_id()),
        for_.def_id(&cx.cache)
    );
    ret.push(clean::Item::from_def_id_and_attrs_and_parts(
        did,
        None,
        clean::ImplItem(Box::new(clean::Impl {
            safety: hir::Safety::Safe,
            generics,
            trait_,
            for_,
            items: trait_items,
            polarity,
            kind: if utils::has_doc_flag(tcx, did, |d| d.fake_variadic.is_some()) {
                ImplKind::FakeVariadic
            } else {
                ImplKind::Normal
            },
            is_deprecated: tcx
                .lookup_deprecation(did)
                .is_some_and(|deprecation| deprecation.is_in_effect()),
        })),
        merged_attrs,
        cfg,
    ));
}

fn build_module(
    cx: &mut DocContext<'_>,
    did: DefId,
    name: Symbol,
    visited: &mut DefIdSet,
) -> clean::Module {
    let items = build_module_items(cx, did, name, visited, &mut FxHashSet::default(), None, None);

    let span = clean::Span::new(cx.tcx.def_span(did));
    clean::Module { items, span }
}

// We are only interested into `Res::Def`. And in there, we only want "items" which get their own
//  rustdoc page. So not `DefKind::Ctor` for example (which is returned by `tcx.module_children()`).
fn should_ignore_res(res: Res) -> bool {
    !matches!(
        res,
        Res::Def(DefKind::Trait, _)
            | Res::Def(DefKind::TraitAlias, _)
            | Res::Def(DefKind::Fn, _)
            | Res::Def(DefKind::Struct, _)
            | Res::Def(DefKind::Union, _)
            | Res::Def(DefKind::TyAlias, _)
            | Res::Def(DefKind::Enum, _)
            | Res::Def(DefKind::ForeignTy, _)
            | Res::Def(DefKind::Variant, _)
            | Res::Def(DefKind::Mod, _)
            | Res::Def(DefKind::Static { .. }, _)
            | Res::Def(DefKind::Const { .. }, _)
            | Res::Def(DefKind::Macro(_), _)
    )
}

fn build_module_items(
    cx: &mut DocContext<'_>,
    module_def_id: DefId,
    module_name: Symbol,
    visited: &mut DefIdSet,
    inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
    allowed_def_ids: Option<&DefIdSet>,
    attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
) -> Vec<clean::Item> {
    let mut items = Vec::new();

    // If we're re-exporting a re-export it may actually re-export something in
    // two namespaces, so the target may be listed twice. Make sure we only
    // visit each node at most once.
    for item in cx.tcx.module_children(module_def_id).iter() {
        if !item.vis.is_public() {
            continue;
        }
        let res = item.res.expect_non_local();
        if let Some(def_id) = res.opt_def_id()
            && let Some(allowed_def_ids) = allowed_def_ids
            && !allowed_def_ids.contains(&def_id)
        {
            continue;
        }
        if let Some(def_id) = res.mod_def_id() {
            // If we're inlining a glob import, it's possible to have
            // two distinct modules with the same name. We don't want to
            // inline it, or mark any of its contents as visited.
            if module_def_id == def_id
                || inlined_names.contains(&(ItemType::Module, item.ident.name))
                || !visited.insert(def_id)
            {
                continue;
            }
        }
        if let Res::PrimTy(p) = res {
            // Primitive types can't be inlined so generate an import instead.
            let prim_ty = clean::PrimitiveType::from(p);
            items.push(clean::Item {
                inner: Box::new(clean::ItemInner {
                    name: None,
                    // We can use the item's `DefId` directly since the only information ever
                    // used from it is `DefId.krate`.
                    item_id: ItemId::DefId(module_def_id),
                    attrs: Default::default(),
                    stability: None,
                    kind: clean::ImportItem(clean::Import::new_simple(
                        item.ident.name,
                        clean::ImportSource {
                            path: clean::Path {
                                res,
                                segments: thin_vec![clean::PathSegment {
                                    name: prim_ty.as_sym(),
                                    args: clean::GenericArgs::AngleBracketed {
                                        args: Default::default(),
                                        constraints: ThinVec::new(),
                                    },
                                }],
                            },
                            did: None,
                        },
                        true,
                    )),
                    cfg: None,
                    inline_stmt_id: None,
                }),
            });
        } else if let Some(def_id) = res.opt_def_id()
            && let Some(reexport) = item.reexport_chain.first()
            && let Some(reexport_def_id) = reexport.id()
            && find_attr!(
                load_attrs(cx.tcx, reexport_def_id),
                Doc(d)
                if d.inline.first().is_some_and(|(inline, _)| *inline == hir::attrs::DocInline::NoInline)
            )
        {
            if should_ignore_res(res) {
                continue;
            }
            // This item is reexported as `no_inline` so it shouldn't be inlined.
            let item = Item::from_def_id_and_parts(
                module_def_id,
                None,
                clean::ImportItem(clean::Import::new_simple(
                    item.ident.name,
                    clean::ImportSource {
                        path: clean::Path {
                            res,
                            segments: thin_vec![
                                clean::PathSegment {
                                    name: module_name,
                                    args: clean::GenericArgs::AngleBracketed {
                                        args: Default::default(),
                                        constraints: ThinVec::new(),
                                    },
                                },
                                clean::PathSegment {
                                    name: cx.tcx.item_name(def_id),
                                    args: clean::GenericArgs::AngleBracketed {
                                        args: Default::default(),
                                        constraints: ThinVec::new(),
                                    },
                                },
                            ],
                        },
                        did: None,
                    },
                    true,
                )),
                cx.tcx,
            );
            items.push(item);
        } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
            items.extend(i)
        }
    }

    items
}

pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
    if let Some(did) = did.as_local() {
        let hir_id = tcx.local_def_id_to_hir_id(did);
        rustc_hir_pretty::id_to_string(&tcx, hir_id)
    } else {
        tcx.rendered_const(did).clone()
    }
}

fn build_const_item(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
    let mut generics = clean_ty_generics(cx, def_id);
    clean::simplify::move_bounds_to_generic_parameters(&mut generics);
    let ty = clean_middle_ty(
        ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip()),
        cx,
        None,
        None,
    );
    clean::Constant { generics, type_: ty, kind: clean::ConstantKind::Extern { def_id } }
}

fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
    clean::Static {
        type_: Box::new(clean_middle_ty(
            ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity().skip_norm_wip()),
            cx,
            Some(did),
            None,
        )),
        mutability: if mutable { Mutability::Mut } else { Mutability::Not },
        expr: None,
    }
}

fn build_macro(
    tcx: TyCtxt<'_>,
    def_id: DefId,
    name: Symbol,
    macro_kinds: MacroKinds,
) -> clean::ItemKind {
    match CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id) {
        LoadedMacro::MacroDef { def, .. } => match macro_kinds {
            MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
                kind: MacroKind::Derive,
                helpers: Vec::new(),
            }),
            MacroKinds::ATTR => clean::ProcMacroItem(clean::ProcMacro {
                kind: MacroKind::Attr,
                helpers: Vec::new(),
            }),
            _ => clean::MacroItem(
                clean::Macro {
                    source: utils::display_macro_source(tcx, name, &def),
                    macro_rules: def.macro_rules,
                },
                macro_kinds,
            ),
        },
        LoadedMacro::ProcMacro(ext) => {
            // Proc macros can only have a single kind
            let kind = match ext.macro_kinds() {
                MacroKinds::BANG => MacroKind::Bang,
                MacroKinds::ATTR => MacroKind::Attr,
                MacroKinds::DERIVE => MacroKind::Derive,
                _ => unreachable!(),
            };
            clean::ProcMacroItem(clean::ProcMacro { kind, helpers: ext.helper_attrs })
        }
    }
}

fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
    let mut ty_bounds = Vec::new();
    g.where_predicates.retain(|pred| match *pred {
        clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
            ty_bounds.extend(bounds.iter().cloned());
            false
        }
        _ => true,
    });
    (g, ty_bounds)
}

pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
    if did.is_local()
        || cx.external_traits.contains_key(&did)
        || cx.active_extern_traits.contains(&did)
    {
        return;
    }

    cx.active_extern_traits.insert(did);

    debug!("record_extern_trait: {did:?}");
    let trait_ = build_trait(cx, did);

    cx.external_traits.insert(did, trait_);
    cx.active_extern_traits.remove(&did);
}
