//! This module defines the primary IR[^1] used in rustdoc together with the procedures that
//! transform rustc data types into it.
//!
//! This IR — commonly referred to as the *cleaned AST* — is modeled after the [AST][ast].
//!
//! There are two kinds of transformation — *cleaning* — procedures:
//!
//! 1. Cleans [HIR][hir] types. Used for user-written code and inlined local re-exports
//!    both found in the local crate.
//! 2. Cleans [`rustc_middle::ty`] types. Used for inlined cross-crate re-exports and anything
//!    output by the trait solver (e.g., when synthesizing blanket and auto-trait impls).
//!    They usually have `ty` or `middle` in their name.
//!
//! Their name is prefixed by `clean_`.
//!
//! Both the HIR and the `rustc_middle::ty` IR are quite removed from the source code.
//! The cleaned AST on the other hand is closer to it which simplifies the rendering process.
//! Furthermore, operating on a single IR instead of two avoids duplicating efforts down the line.
//!
//! This IR is consumed by both the HTML and the JSON backend.
//!
//! [^1]: Intermediate representation.

mod auto_trait;
mod blanket_impl;
pub(crate) mod cfg;
pub(crate) mod inline;
mod render_macro_matchers;
mod simplify;
pub(crate) mod types;
pub(crate) mod utils;

use std::borrow::Cow;
use std::collections::BTreeMap;
use std::mem;

use rustc_ast::token::{Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::codes::*;
use rustc_errors::{FatalError, struct_span_code_err};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
use rustc_hir::{LangItem, PredicateOrigin, find_attr};
use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty};
use rustc_middle::metadata::Reexport;
use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
use rustc_span::ExpnKind;
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_trait_selection::traits::wf::object_region_bounds;
use tracing::{debug, instrument};
use utils::*;
use {rustc_ast as ast, rustc_hir as hir};

pub(crate) use self::cfg::{CfgInfo, extract_cfg_from_attrs};
pub(crate) use self::types::*;
pub(crate) use self::utils::{krate, register_res, synthesize_auto_trait_and_blanket_impls};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
use crate::visit_ast::Module as DocModule;

pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
    let mut items: Vec<Item> = vec![];
    let mut inserted = FxHashSet::default();
    items.extend(doc.foreigns.iter().map(|(item, renamed, import_id)| {
        let item = clean_maybe_renamed_foreign_item(cx, item, *renamed, *import_id);
        if let Some(name) = item.name
            && (cx.document_hidden() || !item.is_doc_hidden())
        {
            inserted.insert((item.type_(), name));
        }
        item
    }));
    items.extend(doc.mods.iter().filter_map(|x| {
        if !inserted.insert((ItemType::Module, x.name)) {
            return None;
        }
        let item = clean_doc_module(x, cx);
        if !cx.document_hidden() && item.is_doc_hidden() {
            // Hidden modules are stripped at a later stage.
            // If a hidden module has the same name as a visible one, we want
            // to keep both of them around.
            inserted.remove(&(ItemType::Module, x.name));
        }
        Some(item)
    }));

    // Split up glob imports from all other items.
    //
    // This covers the case where somebody does an import which should pull in an item,
    // but there's already an item with the same namespace and same name. Rust gives
    // priority to the not-imported one, so we should, too.
    items.extend(doc.items.values().flat_map(|(item, renamed, import_ids)| {
        // First, lower everything other than glob imports.
        if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
            return Vec::new();
        }
        let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids);
        for item in &v {
            if let Some(name) = item.name
                && (cx.document_hidden() || !item.is_doc_hidden())
            {
                inserted.insert((item.type_(), name));
            }
        }
        v
    }));
    items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| {
        let Some(def_id) = res.opt_def_id() else { return Vec::new() };
        let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
        let import = cx.tcx.hir_expect_item(*local_import_id);
        match import.kind {
            hir::ItemKind::Use(path, kind) => {
                let hir::UsePath { segments, span, .. } = *path;
                let path = hir::Path { segments, res: *res, span };
                clean_use_statement_inner(
                    import,
                    Some(name),
                    &path,
                    kind,
                    cx,
                    &mut Default::default(),
                )
            }
            _ => unreachable!(),
        }
    }));
    items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
        // Now we actually lower the imports, skipping everything else.
        if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
            clean_use_statement(item, *renamed, path, hir::UseKind::Glob, cx, &mut inserted)
        } else {
            // skip everything else
            Vec::new()
        }
    }));

    // determine if we should display the inner contents or
    // the outer `mod` item for the source code.

    let span = Span::new({
        let where_outer = doc.where_outer(cx.tcx);
        let sm = cx.sess().source_map();
        let outer = sm.lookup_char_pos(where_outer.lo());
        let inner = sm.lookup_char_pos(doc.where_inner.lo());
        if outer.file.start_pos == inner.file.start_pos {
            // mod foo { ... }
            where_outer
        } else {
            // mod foo; (and a separate SourceFile for the contents)
            doc.where_inner
        }
    });

    let kind = ModuleItem(Module { items, span });
    generate_item_with_correct_attrs(
        cx,
        kind,
        doc.def_id.to_def_id(),
        doc.name,
        doc.import_id.as_slice(),
        doc.renamed,
    )
}

fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool {
    if let hir::Node::Item(item) = tcx.hir_node_by_def_id(import_id)
        && let hir::ItemKind::Use(_, use_kind) = item.kind
    {
        use_kind == hir::UseKind::Glob
    } else {
        false
    }
}

fn generate_item_with_correct_attrs(
    cx: &mut DocContext<'_>,
    kind: ItemKind,
    def_id: DefId,
    name: Symbol,
    import_ids: &[LocalDefId],
    renamed: Option<Symbol>,
) -> Item {
    let target_attrs = inline::load_attrs(cx, def_id);
    let attrs = if !import_ids.is_empty() {
        let mut attrs = Vec::with_capacity(import_ids.len());
        let mut is_inline = false;

        for import_id in import_ids.iter().copied() {
            // glob reexports are treated the same as `#[doc(inline)]` items.
            //
            // For glob re-exports the item may or may not exist to be re-exported (potentially the
            // cfgs on the path up until the glob can be removed, and only cfgs on the globbed item
            // itself matter), for non-inlined re-exports see #85043.
            let import_is_inline =
                hir_attr_lists(inline::load_attrs(cx, import_id.to_def_id()), sym::doc)
                    .get_word_attr(sym::inline)
                    .is_some()
                    || (is_glob_import(cx.tcx, import_id)
                        && (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id)));
            attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline));
            is_inline = is_inline || import_is_inline;
        }
        add_without_unwanted_attributes(&mut attrs, target_attrs, is_inline, None);
        attrs
    } else {
        // We only keep the item's attributes.
        target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect()
    };
    let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);

    let name = renamed.or(Some(name));
    let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, None);
    // FIXME (GuillaumeGomez): Should we also make `inline_stmt_id` a `Vec` instead of an `Option`?
    item.inner.inline_stmt_id = import_ids.first().copied();
    item
}

fn clean_generic_bound<'tcx>(
    bound: &hir::GenericBound<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Option<GenericBound> {
    Some(match bound {
        hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
        hir::GenericBound::Trait(t) => {
            // `T: [const] Destruct` is hidden because `T: Destruct` is a no-op.
            if let hir::BoundConstness::Maybe(_) = t.modifiers.constness
                && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
            {
                return None;
            }

            GenericBound::TraitBound(clean_poly_trait_ref(t, cx), t.modifiers)
        }
        hir::GenericBound::Use(args, ..) => {
            GenericBound::Use(args.iter().map(|arg| clean_precise_capturing_arg(arg, cx)).collect())
        }
    })
}

pub(crate) fn clean_trait_ref_with_constraints<'tcx>(
    cx: &mut DocContext<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
    constraints: ThinVec<AssocItemConstraint>,
) -> Path {
    let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
    if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {kind:?}");
    }
    inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
    let path = clean_middle_path(
        cx,
        trait_ref.def_id(),
        true,
        constraints,
        trait_ref.map_bound(|tr| tr.args),
    );

    debug!(?trait_ref);

    path
}

fn clean_poly_trait_ref_with_constraints<'tcx>(
    cx: &mut DocContext<'tcx>,
    poly_trait_ref: ty::PolyTraitRef<'tcx>,
    constraints: ThinVec<AssocItemConstraint>,
) -> GenericBound {
    GenericBound::TraitBound(
        PolyTrait {
            trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints),
            generic_params: clean_bound_vars(poly_trait_ref.bound_vars(), cx),
        },
        hir::TraitBoundModifiers::NONE,
    )
}

fn clean_lifetime(lifetime: &hir::Lifetime, cx: &DocContext<'_>) -> Lifetime {
    if let Some(
        rbv::ResolvedArg::EarlyBound(did)
        | rbv::ResolvedArg::LateBound(_, _, did)
        | rbv::ResolvedArg::Free(_, did),
    ) = cx.tcx.named_bound_var(lifetime.hir_id)
        && let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt())
    {
        return *lt;
    }
    Lifetime(lifetime.ident.name)
}

pub(crate) fn clean_precise_capturing_arg(
    arg: &hir::PreciseCapturingArg<'_>,
    cx: &DocContext<'_>,
) -> PreciseCapturingArg {
    match arg {
        hir::PreciseCapturingArg::Lifetime(lt) => {
            PreciseCapturingArg::Lifetime(clean_lifetime(lt, cx))
        }
        hir::PreciseCapturingArg::Param(param) => PreciseCapturingArg::Param(param.ident.name),
    }
}

pub(crate) fn clean_const_item_rhs<'tcx>(
    ct_rhs: hir::ConstItemRhs<'tcx>,
    parent: DefId,
) -> ConstantKind {
    match ct_rhs {
        hir::ConstItemRhs::Body(body) => ConstantKind::Local { def_id: parent, body },
        hir::ConstItemRhs::TypeConst(ct) => clean_const(ct),
    }
}

pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind {
    match &constant.kind {
        hir::ConstArgKind::Path(qpath) => {
            ConstantKind::Path { path: qpath_to_string(qpath).into() }
        }
        hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
        hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer,
    }
}

pub(crate) fn clean_middle_const<'tcx>(
    constant: ty::Binder<'tcx, ty::Const<'tcx>>,
    _cx: &mut DocContext<'tcx>,
) -> ConstantKind {
    // FIXME: instead of storing the stringified expression, store `self` directly instead.
    ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }
}

pub(crate) fn clean_middle_region<'tcx>(
    region: ty::Region<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Option<Lifetime> {
    region.get_name(cx.tcx).map(Lifetime)
}

fn clean_where_predicate<'tcx>(
    predicate: &hir::WherePredicate<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
    if !predicate.kind.in_where_clause() {
        return None;
    }
    Some(match predicate.kind {
        hir::WherePredicateKind::BoundPredicate(wbp) => {
            let bound_params = wbp
                .bound_generic_params
                .iter()
                .map(|param| clean_generic_param(cx, None, param))
                .collect();
            WherePredicate::BoundPredicate {
                ty: clean_ty(wbp.bounded_ty, cx),
                bounds: wbp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
                bound_params,
            }
        }

        hir::WherePredicateKind::RegionPredicate(wrp) => WherePredicate::RegionPredicate {
            lifetime: clean_lifetime(wrp.lifetime, cx),
            bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
        },

        // We should never actually reach this case because these predicates should've already been
        // rejected in an earlier compiler pass. This feature isn't fully implemented (#20041).
        hir::WherePredicateKind::EqPredicate(_) => bug!("EqPredicate"),
    })
}

pub(crate) fn clean_predicate<'tcx>(
    predicate: ty::Clause<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
    let bound_predicate = predicate.kind();
    match bound_predicate.skip_binder() {
        ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx),
        ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx)),
        ty::ClauseKind::TypeOutlives(pred) => {
            Some(clean_type_outlives_predicate(bound_predicate.rebind(pred), cx))
        }
        ty::ClauseKind::Projection(pred) => {
            Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
        }
        // FIXME(generic_const_exprs): should this do something?
        ty::ClauseKind::ConstEvaluatable(..)
        | ty::ClauseKind::WellFormed(..)
        | ty::ClauseKind::ConstArgHasType(..)
        | ty::ClauseKind::UnstableFeature(..)
        // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `~const`.
        | ty::ClauseKind::HostEffect(_) => None,
    }
}

fn clean_poly_trait_predicate<'tcx>(
    pred: ty::PolyTraitPredicate<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
    // `T: [const] Destruct` is hidden because `T: Destruct` is a no-op.
    // FIXME(const_trait_impl) check constness
    if Some(pred.skip_binder().def_id()) == cx.tcx.lang_items().destruct_trait() {
        return None;
    }

    let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref);
    Some(WherePredicate::BoundPredicate {
        ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None, None),
        bounds: vec![clean_poly_trait_ref_with_constraints(cx, poly_trait_ref, ThinVec::new())],
        bound_params: Vec::new(),
    })
}

fn clean_region_outlives_predicate<'tcx>(
    pred: ty::RegionOutlivesPredicate<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> WherePredicate {
    let ty::OutlivesPredicate(a, b) = pred;

    WherePredicate::RegionPredicate {
        lifetime: clean_middle_region(a, cx).expect("failed to clean lifetime"),
        bounds: vec![GenericBound::Outlives(
            clean_middle_region(b, cx).expect("failed to clean bounds"),
        )],
    }
}

fn clean_type_outlives_predicate<'tcx>(
    pred: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
    cx: &mut DocContext<'tcx>,
) -> WherePredicate {
    let ty::OutlivesPredicate(ty, lt) = pred.skip_binder();

    WherePredicate::BoundPredicate {
        ty: clean_middle_ty(pred.rebind(ty), cx, None, None),
        bounds: vec![GenericBound::Outlives(
            clean_middle_region(lt, cx).expect("failed to clean lifetimes"),
        )],
        bound_params: Vec::new(),
    }
}

fn clean_middle_term<'tcx>(
    term: ty::Binder<'tcx, ty::Term<'tcx>>,
    cx: &mut DocContext<'tcx>,
) -> Term {
    match term.skip_binder().kind() {
        ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None, None)),
        ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)),
    }
}

fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
    match term {
        hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
        hir::Term::Const(c) => {
            let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No);
            Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx))
        }
    }
}

fn clean_projection_predicate<'tcx>(
    pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
    cx: &mut DocContext<'tcx>,
) -> WherePredicate {
    WherePredicate::EqPredicate {
        lhs: clean_projection(pred.map_bound(|p| p.projection_term), cx, None),
        rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
    }
}

fn clean_projection<'tcx>(
    proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>,
    cx: &mut DocContext<'tcx>,
    parent_def_id: Option<DefId>,
) -> QPathData {
    let trait_ = clean_trait_ref_with_constraints(
        cx,
        proj.map_bound(|proj| proj.trait_ref(cx.tcx)),
        ThinVec::new(),
    );
    let self_type = clean_middle_ty(proj.map_bound(|proj| proj.self_ty()), cx, None, None);
    let self_def_id = match parent_def_id {
        Some(parent_def_id) => cx.tcx.opt_parent(parent_def_id).or(Some(parent_def_id)),
        None => self_type.def_id(&cx.cache),
    };
    let should_fully_qualify = should_fully_qualify_path(self_def_id, &trait_, &self_type);

    QPathData {
        assoc: projection_to_path_segment(proj, cx),
        self_type,
        should_fully_qualify,
        trait_: Some(trait_),
    }
}

fn should_fully_qualify_path(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
    !trait_.segments.is_empty()
        && self_def_id
            .zip(Some(trait_.def_id()))
            .map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
}

fn projection_to_path_segment<'tcx>(
    proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>,
    cx: &mut DocContext<'tcx>,
) -> PathSegment {
    let def_id = proj.skip_binder().def_id;
    let generics = cx.tcx.generics_of(def_id);
    PathSegment {
        name: cx.tcx.item_name(def_id),
        args: GenericArgs::AngleBracketed {
            args: clean_middle_generic_args(
                cx,
                proj.map_bound(|ty| &ty.args[generics.parent_count..]),
                false,
                def_id,
            ),
            constraints: Default::default(),
        },
    }
}

fn clean_generic_param_def(
    def: &ty::GenericParamDef,
    defaults: ParamDefaults,
    cx: &mut DocContext<'_>,
) -> GenericParamDef {
    let (name, kind) = match def.kind {
        ty::GenericParamDefKind::Lifetime => {
            (def.name, GenericParamDefKind::Lifetime { outlives: ThinVec::new() })
        }
        ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
            let default = if let ParamDefaults::Yes = defaults
                && has_default
            {
                Some(clean_middle_ty(
                    ty::Binder::dummy(cx.tcx.type_of(def.def_id).instantiate_identity()),
                    cx,
                    Some(def.def_id),
                    None,
                ))
            } else {
                None
            };
            (
                def.name,
                GenericParamDefKind::Type {
                    bounds: ThinVec::new(), // These are filled in from the where-clauses.
                    default: default.map(Box::new),
                    synthetic,
                },
            )
        }
        ty::GenericParamDefKind::Const { has_default } => (
            def.name,
            GenericParamDefKind::Const {
                ty: Box::new(clean_middle_ty(
                    ty::Binder::dummy(
                        cx.tcx
                            .type_of(def.def_id)
                            .no_bound_vars()
                            .expect("const parameter types cannot be generic"),
                    ),
                    cx,
                    Some(def.def_id),
                    None,
                )),
                default: if let ParamDefaults::Yes = defaults
                    && has_default
                {
                    Some(Box::new(
                        cx.tcx.const_param_default(def.def_id).instantiate_identity().to_string(),
                    ))
                } else {
                    None
                },
            },
        ),
    };

    GenericParamDef { name, def_id: def.def_id, kind }
}

/// Whether to clean generic parameter defaults or not.
enum ParamDefaults {
    Yes,
    No,
}

fn clean_generic_param<'tcx>(
    cx: &mut DocContext<'tcx>,
    generics: Option<&hir::Generics<'tcx>>,
    param: &hir::GenericParam<'tcx>,
) -> GenericParamDef {
    let (name, kind) = match param.kind {
        hir::GenericParamKind::Lifetime { .. } => {
            let outlives = if let Some(generics) = generics {
                generics
                    .outlives_for_param(param.def_id)
                    .filter(|bp| !bp.in_where_clause)
                    .flat_map(|bp| bp.bounds)
                    .map(|bound| match bound {
                        hir::GenericBound::Outlives(lt) => clean_lifetime(lt, cx),
                        _ => panic!(),
                    })
                    .collect()
            } else {
                ThinVec::new()
            };
            (param.name.ident().name, GenericParamDefKind::Lifetime { outlives })
        }
        hir::GenericParamKind::Type { ref default, synthetic } => {
            let bounds = if let Some(generics) = generics {
                generics
                    .bounds_for_param(param.def_id)
                    .filter(|bp| bp.origin != PredicateOrigin::WhereClause)
                    .flat_map(|bp| bp.bounds)
                    .filter_map(|x| clean_generic_bound(x, cx))
                    .collect()
            } else {
                ThinVec::new()
            };
            (
                param.name.ident().name,
                GenericParamDefKind::Type {
                    bounds,
                    default: default.map(|t| clean_ty(t, cx)).map(Box::new),
                    synthetic,
                },
            )
        }
        hir::GenericParamKind::Const { ty, default } => (
            param.name.ident().name,
            GenericParamDefKind::Const {
                ty: Box::new(clean_ty(ty, cx)),
                default: default.map(|ct| {
                    Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string())
                }),
            },
        ),
    };

    GenericParamDef { name, def_id: param.def_id.to_def_id(), kind }
}

/// Synthetic type-parameters are inserted after normal ones.
/// In order for normal parameters to be able to refer to synthetic ones,
/// scans them first.
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
    match param.kind {
        hir::GenericParamKind::Type { synthetic, .. } => synthetic,
        _ => false,
    }
}

/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
///
/// See `lifetime_to_generic_param` in `rustc_ast_lowering` for more information.
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
    matches!(
        param.kind,
        hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided(_) }
    )
}

pub(crate) fn clean_generics<'tcx>(
    gens: &hir::Generics<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Generics {
    let impl_trait_params = gens
        .params
        .iter()
        .filter(|param| is_impl_trait(param))
        .map(|param| {
            let param = clean_generic_param(cx, Some(gens), param);
            match param.kind {
                GenericParamDefKind::Lifetime { .. } => unreachable!(),
                GenericParamDefKind::Type { ref bounds, .. } => {
                    cx.impl_trait_bounds.insert(param.def_id.into(), bounds.to_vec());
                }
                GenericParamDefKind::Const { .. } => unreachable!(),
            }
            param
        })
        .collect::<Vec<_>>();

    let mut bound_predicates = FxIndexMap::default();
    let mut region_predicates = FxIndexMap::default();
    let mut eq_predicates = ThinVec::default();
    for pred in gens.predicates.iter().filter_map(|x| clean_where_predicate(x, cx)) {
        match pred {
            WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
                match bound_predicates.entry(ty) {
                    IndexEntry::Vacant(v) => {
                        v.insert((bounds, bound_params));
                    }
                    IndexEntry::Occupied(mut o) => {
                        // we merge both bounds.
                        for bound in bounds {
                            if !o.get().0.contains(&bound) {
                                o.get_mut().0.push(bound);
                            }
                        }
                        for bound_param in bound_params {
                            if !o.get().1.contains(&bound_param) {
                                o.get_mut().1.push(bound_param);
                            }
                        }
                    }
                }
            }
            WherePredicate::RegionPredicate { lifetime, bounds } => {
                match region_predicates.entry(lifetime) {
                    IndexEntry::Vacant(v) => {
                        v.insert(bounds);
                    }
                    IndexEntry::Occupied(mut o) => {
                        // we merge both bounds.
                        for bound in bounds {
                            if !o.get().contains(&bound) {
                                o.get_mut().push(bound);
                            }
                        }
                    }
                }
            }
            WherePredicate::EqPredicate { lhs, rhs } => {
                eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs });
            }
        }
    }

    let mut params = ThinVec::with_capacity(gens.params.len());
    // In this loop, we gather the generic parameters (`<'a, B: 'a>`) and check if they have
    // bounds in the where predicates. If so, we move their bounds into the where predicates
    // while also preventing duplicates.
    for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
        let mut p = clean_generic_param(cx, Some(gens), p);
        match &mut p.kind {
            GenericParamDefKind::Lifetime { outlives } => {
                if let Some(region_pred) = region_predicates.get_mut(&Lifetime(p.name)) {
                    // We merge bounds in the `where` clause.
                    for outlive in outlives.drain(..) {
                        let outlive = GenericBound::Outlives(outlive);
                        if !region_pred.contains(&outlive) {
                            region_pred.push(outlive);
                        }
                    }
                }
            }
            GenericParamDefKind::Type { bounds, synthetic: false, .. } => {
                if let Some(bound_pred) = bound_predicates.get_mut(&Type::Generic(p.name)) {
                    // We merge bounds in the `where` clause.
                    for bound in bounds.drain(..) {
                        if !bound_pred.0.contains(&bound) {
                            bound_pred.0.push(bound);
                        }
                    }
                }
            }
            GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
                // nothing to do here.
            }
        }
        params.push(p);
    }
    params.extend(impl_trait_params);

    Generics {
        params,
        where_predicates: bound_predicates
            .into_iter()
            .map(|(ty, (bounds, bound_params))| WherePredicate::BoundPredicate {
                ty,
                bounds,
                bound_params,
            })
            .chain(
                region_predicates
                    .into_iter()
                    .map(|(lifetime, bounds)| WherePredicate::RegionPredicate { lifetime, bounds }),
            )
            .chain(eq_predicates)
            .collect(),
    }
}

fn clean_ty_generics<'tcx>(cx: &mut DocContext<'tcx>, def_id: DefId) -> Generics {
    clean_ty_generics_inner(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id))
}

fn clean_ty_generics_inner<'tcx>(
    cx: &mut DocContext<'tcx>,
    gens: &ty::Generics,
    preds: ty::GenericPredicates<'tcx>,
) -> Generics {
    // Don't populate `cx.impl_trait_bounds` before cleaning where clauses,
    // since `clean_predicate` would consume them.
    let mut impl_trait = BTreeMap::<u32, Vec<GenericBound>>::default();

    let params: ThinVec<_> = gens
        .own_params
        .iter()
        .filter(|param| match param.kind {
            ty::GenericParamDefKind::Lifetime => !param.is_anonymous_lifetime(),
            ty::GenericParamDefKind::Type { synthetic, .. } => {
                if param.name == kw::SelfUpper {
                    debug_assert_eq!(param.index, 0);
                    return false;
                }
                if synthetic {
                    impl_trait.insert(param.index, vec![]);
                    return false;
                }
                true
            }
            ty::GenericParamDefKind::Const { .. } => true,
        })
        .map(|param| clean_generic_param_def(param, ParamDefaults::Yes, cx))
        .collect();

    // param index -> [(trait DefId, associated type name & generics, term)]
    let mut impl_trait_proj =
        FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();

    let where_predicates = preds
        .predicates
        .iter()
        .flat_map(|(pred, _)| {
            let mut proj_pred = None;
            let param_idx = {
                let bound_p = pred.kind();
                match bound_p.skip_binder() {
                    ty::ClauseKind::Trait(pred) if let ty::Param(param) = pred.self_ty().kind() => {
                        Some(param.index)
                    }
                    ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg))
                        if let ty::Param(param) = ty.kind() =>
                    {
                        Some(param.index)
                    }
                    ty::ClauseKind::Projection(p)
                        if let ty::Param(param) = p.projection_term.self_ty().kind() =>
                    {
                        proj_pred = Some(bound_p.rebind(p));
                        Some(param.index)
                    }
                    _ => None,
                }
            };

            if let Some(param_idx) = param_idx
                && let Some(bounds) = impl_trait.get_mut(&param_idx)
            {
                let pred = clean_predicate(*pred, cx)?;

                bounds.extend(pred.get_bounds().into_iter().flatten().cloned());

                if let Some(pred) = proj_pred {
                    let lhs = clean_projection(pred.map_bound(|p| p.projection_term), cx, None);
                    impl_trait_proj.entry(param_idx).or_default().push((
                        lhs.trait_.unwrap().def_id(),
                        lhs.assoc,
                        pred.map_bound(|p| p.term),
                    ));
                }

                return None;
            }

            Some(pred)
        })
        .collect::<Vec<_>>();

    for (idx, mut bounds) in impl_trait {
        let mut has_sized = false;
        bounds.retain(|b| {
            if b.is_sized_bound(cx) {
                has_sized = true;
                false
            } else if b.is_meta_sized_bound(cx) {
                // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
                // is shown and none of the new sizedness traits leak into documentation.
                false
            } else {
                true
            }
        });
        if !has_sized {
            bounds.push(GenericBound::maybe_sized(cx));
        }

        // Move trait bounds to the front.
        bounds.sort_by_key(|b| !b.is_trait_bound());

        // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
        // Since all potential trait bounds are at the front we can just check the first bound.
        if bounds.first().is_none_or(|b| !b.is_trait_bound()) {
            bounds.insert(0, GenericBound::sized(cx));
        }

        if let Some(proj) = impl_trait_proj.remove(&idx) {
            for (trait_did, name, rhs) in proj {
                let rhs = clean_middle_term(rhs, cx);
                simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
            }
        }

        cx.impl_trait_bounds.insert(idx.into(), bounds);
    }

    // Now that `cx.impl_trait_bounds` is populated, we can process
    // remaining predicates which could contain `impl Trait`.
    let where_predicates =
        where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect();

    let mut generics = Generics { params, where_predicates };
    simplify::sized_bounds(cx, &mut generics);
    generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates);
    generics
}

fn clean_ty_alias_inner_type<'tcx>(
    ty: Ty<'tcx>,
    cx: &mut DocContext<'tcx>,
    ret: &mut Vec<Item>,
) -> Option<TypeAliasInnerType> {
    let ty::Adt(adt_def, args) = ty.kind() else {
        return None;
    };

    if !adt_def.did().is_local() {
        cx.with_param_env(adt_def.did(), |cx| {
            inline::build_impls(cx, adt_def.did(), None, ret);
        });
    }

    Some(if adt_def.is_enum() {
        let variants: rustc_index::IndexVec<_, _> = adt_def
            .variants()
            .iter()
            .map(|variant| clean_variant_def_with_args(variant, args, cx))
            .collect();

        if !adt_def.did().is_local() {
            inline::record_extern_fqn(cx, adt_def.did(), ItemType::Enum);
        }

        TypeAliasInnerType::Enum {
            variants,
            is_non_exhaustive: adt_def.is_variant_list_non_exhaustive(),
        }
    } else {
        let variant = adt_def
            .variants()
            .iter()
            .next()
            .unwrap_or_else(|| bug!("a struct or union should always have one variant def"));

        let fields: Vec<_> =
            clean_variant_def_with_args(variant, args, cx).kind.inner_items().cloned().collect();

        if adt_def.is_struct() {
            if !adt_def.did().is_local() {
                inline::record_extern_fqn(cx, adt_def.did(), ItemType::Struct);
            }
            TypeAliasInnerType::Struct { ctor_kind: variant.ctor_kind(), fields }
        } else {
            if !adt_def.did().is_local() {
                inline::record_extern_fqn(cx, adt_def.did(), ItemType::Union);
            }
            TypeAliasInnerType::Union { fields }
        }
    })
}

fn clean_proc_macro<'tcx>(
    item: &hir::Item<'tcx>,
    name: &mut Symbol,
    kind: MacroKind,
    cx: &mut DocContext<'tcx>,
) -> ItemKind {
    if kind != MacroKind::Derive {
        return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
    }
    let attrs = cx.tcx.hir_attrs(item.hir_id());
    let Some((trait_name, helper_attrs)) = find_attr!(attrs, AttributeKind::ProcMacroDerive { trait_name, helper_attrs, ..} => (*trait_name, helper_attrs))
    else {
        return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
    };
    *name = trait_name;
    let helpers = helper_attrs.iter().copied().collect();

    ProcMacroItem(ProcMacro { kind, helpers })
}

fn clean_fn_or_proc_macro<'tcx>(
    item: &hir::Item<'tcx>,
    sig: &hir::FnSig<'tcx>,
    generics: &hir::Generics<'tcx>,
    body_id: hir::BodyId,
    name: &mut Symbol,
    cx: &mut DocContext<'tcx>,
) -> ItemKind {
    let attrs = cx.tcx.hir_attrs(item.hir_id());
    let macro_kind = if find_attr!(attrs, AttributeKind::ProcMacro(..)) {
        Some(MacroKind::Bang)
    } else if find_attr!(attrs, AttributeKind::ProcMacroDerive { .. }) {
        Some(MacroKind::Derive)
    } else if find_attr!(attrs, AttributeKind::ProcMacroAttribute(..)) {
        Some(MacroKind::Attr)
    } else {
        None
    };

    match macro_kind {
        Some(kind) => clean_proc_macro(item, name, kind, cx),
        None => {
            let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id));
            clean_fn_decl_legacy_const_generics(&mut func, attrs);
            FunctionItem(func)
        }
    }
}

/// This is needed to make it more "readable" when documenting functions using
/// `rustc_legacy_const_generics`. More information in
/// <https://github.com/rust-lang/rust/issues/83167>.
fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attribute]) {
    for meta_item_list in attrs
        .iter()
        .filter(|a| a.has_name(sym::rustc_legacy_const_generics))
        .filter_map(|a| a.meta_item_list())
    {
        for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.lit()).enumerate() {
            match literal.kind {
                ast::LitKind::Int(a, _) => {
                    let GenericParamDef { name, kind, .. } = func.generics.params.remove(0);
                    if let GenericParamDefKind::Const { ty, .. } = kind {
                        func.decl.inputs.insert(
                            a.get() as _,
                            Parameter { name: Some(name), type_: *ty, is_const: true },
                        );
                    } else {
                        panic!("unexpected non const in position {pos}");
                    }
                }
                _ => panic!("invalid arg index"),
            }
        }
    }
}

enum ParamsSrc<'tcx> {
    Body(hir::BodyId),
    Idents(&'tcx [Option<Ident>]),
}

fn clean_function<'tcx>(
    cx: &mut DocContext<'tcx>,
    sig: &hir::FnSig<'tcx>,
    generics: &hir::Generics<'tcx>,
    params: ParamsSrc<'tcx>,
) -> Box<Function> {
    let (generics, decl) = enter_impl_trait(cx, |cx| {
        // NOTE: Generics must be cleaned before params.
        let generics = clean_generics(generics, cx);
        let params = match params {
            ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id),
            // Let's not perpetuate anon params from Rust 2015; use `_` for them.
            ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| {
                Some(ident.map_or(kw::Underscore, |ident| ident.name))
            }),
        };
        let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params);
        (generics, decl)
    });
    Box::new(Function { decl, generics })
}

fn clean_params<'tcx>(
    cx: &mut DocContext<'tcx>,
    types: &[hir::Ty<'tcx>],
    idents: &[Option<Ident>],
    postprocess: impl Fn(Option<Ident>) -> Option<Symbol>,
) -> Vec<Parameter> {
    types
        .iter()
        .enumerate()
        .map(|(i, ty)| Parameter {
            name: postprocess(idents[i]),
            type_: clean_ty(ty, cx),
            is_const: false,
        })
        .collect()
}

fn clean_params_via_body<'tcx>(
    cx: &mut DocContext<'tcx>,
    types: &[hir::Ty<'tcx>],
    body_id: hir::BodyId,
) -> Vec<Parameter> {
    types
        .iter()
        .zip(cx.tcx.hir_body(body_id).params)
        .map(|(ty, param)| Parameter {
            name: Some(name_from_pat(param.pat)),
            type_: clean_ty(ty, cx),
            is_const: false,
        })
        .collect()
}

fn clean_fn_decl_with_params<'tcx>(
    cx: &mut DocContext<'tcx>,
    decl: &hir::FnDecl<'tcx>,
    header: Option<&hir::FnHeader>,
    params: Vec<Parameter>,
) -> FnDecl {
    let mut output = match decl.output {
        hir::FnRetTy::Return(typ) => clean_ty(typ, cx),
        hir::FnRetTy::DefaultReturn(..) => Type::Tuple(Vec::new()),
    };
    if let Some(header) = header
        && header.is_async()
    {
        output = output.sugared_async_return_type();
    }
    FnDecl { inputs: params, output, c_variadic: decl.c_variadic }
}

fn clean_poly_fn_sig<'tcx>(
    cx: &mut DocContext<'tcx>,
    did: Option<DefId>,
    sig: ty::PolyFnSig<'tcx>,
) -> FnDecl {
    let mut output = clean_middle_ty(sig.output(), cx, None, None);

    // If the return type isn't an `impl Trait`, we can safely assume that this
    // function isn't async without needing to execute the query `asyncness` at
    // all which gives us a noticeable performance boost.
    if let Some(did) = did
        && let Type::ImplTrait(_) = output
        && cx.tcx.asyncness(did).is_async()
    {
        output = output.sugared_async_return_type();
    }

    let mut idents = did.map(|did| cx.tcx.fn_arg_idents(did)).unwrap_or_default().iter().copied();

    // If this comes from a fn item, let's not perpetuate anon params from Rust 2015; use `_` for them.
    // If this comes from a fn ptr ty, we just keep params unnamed since it's more conventional stylistically.
    // Since the param name is not part of the semantic type, these params never bear a name unlike
    // in the HIR case, thus we can't perform any fancy fallback logic unlike `clean_bare_fn_ty`.
    let fallback = did.map(|_| kw::Underscore);

    let params = sig
        .inputs()
        .iter()
        .map(|ty| Parameter {
            name: idents.next().flatten().map(|ident| ident.name).or(fallback),
            type_: clean_middle_ty(ty.map_bound(|ty| *ty), cx, None, None),
            is_const: false,
        })
        .collect();

    FnDecl { inputs: params, output, c_variadic: sig.skip_binder().c_variadic }
}

fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
    let path = clean_path(trait_ref.path, cx);
    register_res(cx, path.res);
    path
}

fn clean_poly_trait_ref<'tcx>(
    poly_trait_ref: &hir::PolyTraitRef<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> PolyTrait {
    PolyTrait {
        trait_: clean_trait_ref(&poly_trait_ref.trait_ref, cx),
        generic_params: poly_trait_ref
            .bound_generic_params
            .iter()
            .filter(|p| !is_elided_lifetime(p))
            .map(|x| clean_generic_param(cx, None, x))
            .collect(),
    }
}

fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
    let local_did = trait_item.owner_id.to_def_id();
    cx.with_param_env(local_did, |cx| {
        let inner = match trait_item.kind {
            hir::TraitItemKind::Const(ty, Some(default)) => {
                ProvidedAssocConstItem(Box::new(Constant {
                    generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
                    kind: clean_const_item_rhs(default, local_did),
                    type_: clean_ty(ty, cx),
                }))
            }
            hir::TraitItemKind::Const(ty, None) => {
                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
            }
            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
                let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body));
                MethodItem(m, None)
            }
            hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => {
                let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Idents(idents));
                RequiredMethodItem(m)
            }
            hir::TraitItemKind::Type(bounds, Some(default)) => {
                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
                let item_type =
                    clean_middle_ty(ty::Binder::dummy(lower_ty(cx.tcx, default)), cx, None, None);
                AssocTypeItem(
                    Box::new(TypeAlias {
                        type_: clean_ty(default, cx),
                        generics,
                        inner_type: None,
                        item_type: Some(item_type),
                    }),
                    bounds,
                )
            }
            hir::TraitItemKind::Type(bounds, None) => {
                let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
                let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
                RequiredAssocTypeItem(generics, bounds)
            }
        };
        Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
    })
}

pub(crate) fn clean_impl_item<'tcx>(
    impl_: &hir::ImplItem<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Item {
    let local_did = impl_.owner_id.to_def_id();
    cx.with_param_env(local_did, |cx| {
        let inner = match impl_.kind {
            hir::ImplItemKind::Const(ty, expr) => ImplAssocConstItem(Box::new(Constant {
                generics: clean_generics(impl_.generics, cx),
                kind: clean_const_item_rhs(expr, local_did),
                type_: clean_ty(ty, cx),
            })),
            hir::ImplItemKind::Fn(ref sig, body) => {
                let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body));
                let defaultness = match impl_.impl_kind {
                    hir::ImplItemImplKind::Inherent { .. } => hir::Defaultness::Final,
                    hir::ImplItemImplKind::Trait { defaultness, .. } => defaultness,
                };
                MethodItem(m, Some(defaultness))
            }
            hir::ImplItemKind::Type(hir_ty) => {
                let type_ = clean_ty(hir_ty, cx);
                let generics = clean_generics(impl_.generics, cx);
                let item_type =
                    clean_middle_ty(ty::Binder::dummy(lower_ty(cx.tcx, hir_ty)), cx, None, None);
                AssocTypeItem(
                    Box::new(TypeAlias {
                        type_,
                        generics,
                        inner_type: None,
                        item_type: Some(item_type),
                    }),
                    Vec::new(),
                )
            }
        };

        Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx)
    })
}

pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocContext<'_>) -> Item {
    let tcx = cx.tcx;
    let kind = match assoc_item.kind {
        ty::AssocKind::Const { .. } => {
            let ty = clean_middle_ty(
                ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()),
                cx,
                Some(assoc_item.def_id),
                None,
            );

            let mut generics = clean_ty_generics(cx, assoc_item.def_id);
            simplify::move_bounds_to_generic_parameters(&mut generics);

            match assoc_item.container {
                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                    ImplAssocConstItem(Box::new(Constant {
                        generics,
                        kind: ConstantKind::Extern { def_id: assoc_item.def_id },
                        type_: ty,
                    }))
                }
                ty::AssocContainer::Trait => {
                    if tcx.defaultness(assoc_item.def_id).has_value() {
                        ProvidedAssocConstItem(Box::new(Constant {
                            generics,
                            kind: ConstantKind::Extern { def_id: assoc_item.def_id },
                            type_: ty,
                        }))
                    } else {
                        RequiredAssocConstItem(generics, Box::new(ty))
                    }
                }
            }
        }
        ty::AssocKind::Fn { has_self, .. } => {
            let mut item = inline::build_function(cx, assoc_item.def_id);

            if has_self {
                let self_ty = match assoc_item.container {
                    ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => {
                        tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
                    }
                    ty::AssocContainer::Trait => tcx.types.self_param,
                };
                let self_param_ty =
                    tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
                if self_param_ty == self_ty {
                    item.decl.inputs[0].type_ = SelfTy;
                } else if let ty::Ref(_, ty, _) = *self_param_ty.kind()
                    && ty == self_ty
                {
                    match item.decl.inputs[0].type_ {
                        BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
                        _ => unreachable!(),
                    }
                }
            }

            let provided = match assoc_item.container {
                ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true,
                ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(),
            };
            if provided {
                let defaultness = match assoc_item.container {
                    ty::AssocContainer::TraitImpl(_) => Some(assoc_item.defaultness(tcx)),
                    ty::AssocContainer::InherentImpl | ty::AssocContainer::Trait => None,
                };
                MethodItem(item, defaultness)
            } else {
                RequiredMethodItem(item)
            }
        }
        ty::AssocKind::Type { .. } => {
            let my_name = assoc_item.name();

            fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                match (&param.kind, arg) {
                    (GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
                        if *ty == param.name =>
                    {
                        true
                    }
                    (GenericParamDefKind::Lifetime { .. }, GenericArg::Lifetime(Lifetime(lt)))
                        if *lt == param.name =>
                    {
                        true
                    }
                    (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &**c {
                        ConstantKind::TyConst { expr } => **expr == *param.name.as_str(),
                        _ => false,
                    },
                    _ => false,
                }
            }

            let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
            if let ty::AssocContainer::Trait = assoc_item.container {
                let bounds = tcx.explicit_item_bounds(assoc_item.def_id).iter_identity_copied();
                predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
            }
            let mut generics = clean_ty_generics_inner(
                cx,
                tcx.generics_of(assoc_item.def_id),
                ty::GenericPredicates { parent: None, predicates },
            );
            simplify::move_bounds_to_generic_parameters(&mut generics);

            if let ty::AssocContainer::Trait = assoc_item.container {
                // Move bounds that are (likely) directly attached to the associated type
                // from the where-clause to the associated type.
                // There is no guarantee that this is what the user actually wrote but we have
                // no way of knowing.
                let mut bounds: Vec<GenericBound> = Vec::new();
                generics.where_predicates.retain_mut(|pred| match *pred {
                    WherePredicate::BoundPredicate {
                        ty:
                            QPath(box QPathData {
                                ref assoc,
                                ref self_type,
                                trait_: Some(ref trait_),
                                ..
                            }),
                        bounds: ref mut pred_bounds,
                        ..
                    } => {
                        if assoc.name != my_name {
                            return true;
                        }
                        if trait_.def_id() != assoc_item.container_id(tcx) {
                            return true;
                        }
                        if *self_type != SelfTy {
                            return true;
                        }
                        match &assoc.args {
                            GenericArgs::AngleBracketed { args, constraints } => {
                                if !constraints.is_empty()
                                    || generics
                                        .params
                                        .iter()
                                        .zip(args.iter())
                                        .any(|(param, arg)| !param_eq_arg(param, arg))
                                {
                                    return true;
                                }
                            }
                            GenericArgs::Parenthesized { .. } => {
                                // The only time this happens is if we're inside the rustdoc for Fn(),
                                // which only has one associated type, which is not a GAT, so whatever.
                            }
                            GenericArgs::ReturnTypeNotation => {
                                // Never move these.
                            }
                        }
                        bounds.extend(mem::take(pred_bounds));
                        false
                    }
                    _ => true,
                });

                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)
                });

                // Our Sized/?Sized bound didn't get handled when creating the generics
                // because we didn't actually get our whole set of bounds until just now
                // (some of them may have come from the trait). If we do have a sized
                // bound, we remove it, and if we don't then we add the `?Sized` bound
                // at the end.
                match bounds.iter().position(|b| b.is_sized_bound(cx)) {
                    Some(i) => {
                        bounds.remove(i);
                    }
                    None => bounds.push(GenericBound::maybe_sized(cx)),
                }

                if tcx.defaultness(assoc_item.def_id).has_value() {
                    AssocTypeItem(
                        Box::new(TypeAlias {
                            type_: clean_middle_ty(
                                ty::Binder::dummy(
                                    tcx.type_of(assoc_item.def_id).instantiate_identity(),
                                ),
                                cx,
                                Some(assoc_item.def_id),
                                None,
                            ),
                            generics,
                            inner_type: None,
                            item_type: None,
                        }),
                        bounds,
                    )
                } else {
                    RequiredAssocTypeItem(generics, bounds)
                }
            } else {
                AssocTypeItem(
                    Box::new(TypeAlias {
                        type_: clean_middle_ty(
                            ty::Binder::dummy(
                                tcx.type_of(assoc_item.def_id).instantiate_identity(),
                            ),
                            cx,
                            Some(assoc_item.def_id),
                            None,
                        ),
                        generics,
                        inner_type: None,
                        item_type: None,
                    }),
                    // Associated types inside trait or inherent impls are not allowed to have
                    // item bounds. Thus we don't attempt to move any bounds there.
                    Vec::new(),
                )
            }
        }
    };

    Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx)
}

fn first_non_private_clean_path<'tcx>(
    cx: &mut DocContext<'tcx>,
    path: &hir::Path<'tcx>,
    new_path_segments: &'tcx [hir::PathSegment<'tcx>],
    new_path_span: rustc_span::Span,
) -> Path {
    let new_hir_path =
        hir::Path { segments: new_path_segments, res: path.res, span: new_path_span };
    let mut new_clean_path = clean_path(&new_hir_path, cx);
    // In here we need to play with the path data one last time to provide it the
    // missing `args` and `res` of the final `Path` we get, which, since it comes
    // from a re-export, doesn't have the generics that were originally there, so
    // we add them by hand.
    if let Some(path_last) = path.segments.last().as_ref()
        && let Some(new_path_last) = new_clean_path.segments[..].last_mut()
        && let Some(path_last_args) = path_last.args.as_ref()
        && path_last.args.is_some()
    {
        assert!(new_path_last.args.is_empty());
        new_path_last.args = clean_generic_args(path_last_args, cx);
    }
    new_clean_path
}

/// The goal of this function is to return the first `Path` which is not private (ie not private
/// or `doc(hidden)`). If it's not possible, it'll return the "end type".
///
/// If the path is not a re-export or is public, it'll return `None`.
fn first_non_private<'tcx>(
    cx: &mut DocContext<'tcx>,
    hir_id: hir::HirId,
    path: &hir::Path<'tcx>,
) -> Option<Path> {
    let target_def_id = path.res.opt_def_id()?;
    let (parent_def_id, ident) = match &path.segments {
        [] => return None,
        // Relative paths are available in the same scope as the owner.
        [leaf] => (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident),
        // So are self paths.
        [parent, leaf] if parent.ident.name == kw::SelfLower => {
            (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident)
        }
        // Crate paths are not. We start from the crate root.
        [parent, leaf] if matches!(parent.ident.name, kw::Crate | kw::PathRoot) => {
            (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
        }
        [parent, leaf] if parent.ident.name == kw::Super => {
            let parent_mod = cx.tcx.parent_module(hir_id);
            if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod.to_local_def_id()) {
                (super_parent, leaf.ident)
            } else {
                // If we can't find the parent of the parent, then the parent is already the crate.
                (LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
            }
        }
        // Absolute paths are not. We start from the parent of the item.
        [.., parent, leaf] => (parent.res.opt_def_id()?.as_local()?, leaf.ident),
    };
    // First we try to get the `DefId` of the item.
    for child in
        cx.tcx.module_children_local(parent_def_id).iter().filter(move |c| c.ident == ident)
    {
        if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = child.res {
            continue;
        }

        if let Some(def_id) = child.res.opt_def_id()
            && target_def_id == def_id
        {
            let mut last_path_res = None;
            'reexps: for reexp in child.reexport_chain.iter() {
                if let Some(use_def_id) = reexp.id()
                    && let Some(local_use_def_id) = use_def_id.as_local()
                    && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id)
                    && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind
                {
                    for res in path.res.present_items() {
                        if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
                            continue;
                        }
                        if (cx.document_hidden() ||
                            !cx.tcx.is_doc_hidden(use_def_id)) &&
                            // We never check for "cx.document_private()"
                            // because if a re-export is not fully public, it's never
                            // documented.
                            cx.tcx.local_visibility(local_use_def_id).is_public()
                        {
                            break 'reexps;
                        }
                        last_path_res = Some((path, res));
                        continue 'reexps;
                    }
                }
            }
            if !child.reexport_chain.is_empty() {
                // So in here, we use the data we gathered from iterating the reexports. If
                // `last_path_res` is set, it can mean two things:
                //
                // 1. We found a public reexport.
                // 2. We didn't find a public reexport so it's the "end type" path.
                if let Some((new_path, _)) = last_path_res {
                    return Some(first_non_private_clean_path(
                        cx,
                        path,
                        new_path.segments,
                        new_path.span,
                    ));
                }
                // If `last_path_res` is `None`, it can mean two things:
                //
                // 1. The re-export is public, no need to change anything, just use the path as is.
                // 2. Nothing was found, so let's just return the original path.
                return None;
            }
        }
    }
    None
}

fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
    let hir::Ty { hir_id, span, ref kind } = *hir_ty;
    let hir::TyKind::Path(qpath) = kind else { unreachable!() };

    match qpath {
        hir::QPath::Resolved(None, path) => {
            if let Res::Def(DefKind::TyParam, did) = path.res {
                if let Some(new_ty) = cx.args.get(&did).and_then(|p| p.as_ty()).cloned() {
                    return new_ty;
                }
                if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
                    return ImplTrait(bounds);
                }
            }

            if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
                expanded
            } else {
                // First we check if it's a private re-export.
                let path = if let Some(path) = first_non_private(cx, hir_id, path) {
                    path
                } else {
                    clean_path(path, cx)
                };
                resolve_type(cx, path)
            }
        }
        hir::QPath::Resolved(Some(qself), p) => {
            // Try to normalize `<X as Y>::T` to a type
            let ty = lower_ty(cx.tcx, hir_ty);
            // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
            if !ty.has_escaping_bound_vars()
                && let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty))
            {
                return clean_middle_ty(normalized_value, cx, None, None);
            }

            let trait_segments = &p.segments[..p.segments.len() - 1];
            let trait_def = cx.tcx.parent(p.res.def_id());
            let trait_ = self::Path {
                res: Res::Def(DefKind::Trait, trait_def),
                segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
            };
            register_res(cx, trait_.res);
            let self_def_id = DefId::local(qself.hir_id.owner.def_id.local_def_index);
            let self_type = clean_ty(qself, cx);
            let should_fully_qualify =
                should_fully_qualify_path(Some(self_def_id), &trait_, &self_type);
            Type::QPath(Box::new(QPathData {
                assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
                should_fully_qualify,
                self_type,
                trait_: Some(trait_),
            }))
        }
        hir::QPath::TypeRelative(qself, segment) => {
            let ty = lower_ty(cx.tcx, hir_ty);
            let self_type = clean_ty(qself, cx);

            let (trait_, should_fully_qualify) = match ty.kind() {
                ty::Alias(ty::Projection, proj) => {
                    let res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
                    let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
                    register_res(cx, trait_.res);
                    let self_def_id = res.opt_def_id();
                    let should_fully_qualify =
                        should_fully_qualify_path(self_def_id, &trait_, &self_type);

                    (Some(trait_), should_fully_qualify)
                }
                ty::Alias(ty::Inherent, _) => (None, false),
                // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
                ty::Error(_) => return Type::Infer,
                _ => bug!("clean: expected associated type, found `{ty:?}`"),
            };

            Type::QPath(Box::new(QPathData {
                assoc: clean_path_segment(segment, cx),
                should_fully_qualify,
                self_type,
                trait_,
            }))
        }
    }
}

fn maybe_expand_private_type_alias<'tcx>(
    cx: &mut DocContext<'tcx>,
    path: &hir::Path<'tcx>,
) -> Option<Type> {
    let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
    // Substitute private type aliases
    let def_id = def_id.as_local()?;
    let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id())
        && !cx.current_type_aliases.contains_key(&def_id.to_def_id())
    {
        &cx.tcx.hir_expect_item(def_id).kind
    } else {
        return None;
    };
    let hir::ItemKind::TyAlias(_, generics, ty) = alias else { return None };

    let final_seg = &path.segments.last().expect("segments were empty");
    let mut args = DefIdMap::default();
    let generic_args = final_seg.args();

    let mut indices: hir::GenericParamCount = Default::default();
    for param in generics.params.iter() {
        match param.kind {
            hir::GenericParamKind::Lifetime { .. } => {
                let mut j = 0;
                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
                    hir::GenericArg::Lifetime(lt) => {
                        if indices.lifetimes == j {
                            return Some(lt);
                        }
                        j += 1;
                        None
                    }
                    _ => None,
                });
                if let Some(lt) = lifetime {
                    let lt = if !lt.is_anonymous() {
                        clean_lifetime(lt, cx)
                    } else {
                        Lifetime::elided()
                    };
                    args.insert(param.def_id.to_def_id(), GenericArg::Lifetime(lt));
                }
                indices.lifetimes += 1;
            }
            hir::GenericParamKind::Type { ref default, .. } => {
                let mut j = 0;
                let type_ = generic_args.args.iter().find_map(|arg| match arg {
                    hir::GenericArg::Type(ty) => {
                        if indices.types == j {
                            return Some(ty.as_unambig_ty());
                        }
                        j += 1;
                        None
                    }
                    _ => None,
                });
                if let Some(ty) = type_.or(*default) {
                    args.insert(param.def_id.to_def_id(), GenericArg::Type(clean_ty(ty, cx)));
                }
                indices.types += 1;
            }
            // FIXME(#82852): Instantiate const parameters.
            hir::GenericParamKind::Const { .. } => {}
        }
    }

    Some(cx.enter_alias(args, def_id.to_def_id(), |cx| {
        cx.with_param_env(def_id.to_def_id(), |cx| clean_ty(ty, cx))
    }))
}

pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
    use rustc_hir::*;

    match ty.kind {
        TyKind::Never => Primitive(PrimitiveType::Never),
        TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
        TyKind::Ref(l, ref m) => {
            let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(l, cx)) };
            BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
        }
        TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
        TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()),
        TyKind::Array(ty, const_arg) => {
            // NOTE(min_const_generics): We can't use `const_eval_poly` for constants
            // as we currently do not supply the parent generics to anonymous constants
            // but do allow `ConstKind::Param`.
            //
            // `const_eval_poly` tries to first substitute generic parameters which
            // results in an ICE while manually constructing the constant and using `eval`
            // does nothing for `ConstKind::Param`.
            let length = match const_arg.kind {
                hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => "_".to_string(),
                hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => {
                    let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
                    let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
                    let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
                    print_const(cx, ct)
                }
                hir::ConstArgKind::Path(..) => {
                    let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
                    print_const(cx, ct)
                }
            };
            Array(Box::new(clean_ty(ty, cx)), length.into())
        }
        TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
        TyKind::OpaqueDef(ty) => {
            ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
        }
        TyKind::Path(_) => clean_qpath(ty, cx),
        TyKind::TraitObject(bounds, lifetime) => {
            let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
            let lifetime = if !lifetime.is_elided() {
                Some(clean_lifetime(lifetime.pointer(), cx))
            } else {
                None
            };
            DynTrait(bounds, lifetime)
        }
        TyKind::FnPtr(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
        TyKind::UnsafeBinder(unsafe_binder_ty) => {
            UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx)))
        }
        // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
        TyKind::Infer(())
        | TyKind::Err(_)
        | TyKind::Typeof(..)
        | TyKind::InferDelegation(..)
        | TyKind::TraitAscription(_) => Infer,
    }
}

/// Returns `None` if the type could not be normalized
fn normalize<'tcx>(
    cx: &DocContext<'tcx>,
    ty: ty::Binder<'tcx, Ty<'tcx>>,
) -> Option<ty::Binder<'tcx, Ty<'tcx>>> {
    // HACK: low-churn fix for #79459 while we wait for a trait normalization fix
    if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
        return None;
    }

    use rustc_middle::traits::ObligationCause;
    use rustc_trait_selection::infer::TyCtxtInferExt;
    use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;

    // Try to normalize `<X as Y>::T` to a type
    let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
    let normalized = infcx
        .at(&ObligationCause::dummy(), cx.param_env)
        .query_normalize(ty)
        .map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
    match normalized {
        Ok(normalized_value) => {
            debug!("normalized {ty:?} to {normalized_value:?}");
            Some(normalized_value)
        }
        Err(err) => {
            debug!("failed to normalize {ty:?}: {err:?}");
            None
        }
    }
}

fn clean_trait_object_lifetime_bound<'tcx>(
    region: ty::Region<'tcx>,
    container: Option<ContainerTy<'_, 'tcx>>,
    preds: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
    tcx: TyCtxt<'tcx>,
) -> Option<Lifetime> {
    if can_elide_trait_object_lifetime_bound(region, container, preds, tcx) {
        return None;
    }

    // Since there is a semantic difference between an implicitly elided (i.e. "defaulted") object
    // lifetime and an explicitly elided object lifetime (`'_`), we intentionally don't hide the
    // latter contrary to `clean_middle_region`.
    match region.kind() {
        ty::ReStatic => Some(Lifetime::statik()),
        ty::ReEarlyParam(region) => Some(Lifetime(region.name)),
        ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id), .. }) => {
            Some(Lifetime(tcx.item_name(def_id)))
        }
        ty::ReBound(..)
        | ty::ReLateParam(_)
        | ty::ReVar(_)
        | ty::RePlaceholder(_)
        | ty::ReErased
        | ty::ReError(_) => None,
    }
}

fn can_elide_trait_object_lifetime_bound<'tcx>(
    region: ty::Region<'tcx>,
    container: Option<ContainerTy<'_, 'tcx>>,
    preds: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
    tcx: TyCtxt<'tcx>,
) -> bool {
    // Below we quote extracts from https://doc.rust-lang.org/stable/reference/lifetime-elision.html#default-trait-object-lifetimes

    // > If the trait object is used as a type argument of a generic type then the containing type is
    // > first used to try to infer a bound.
    let default = container
        .map_or(ObjectLifetimeDefault::Empty, |container| container.object_lifetime_default(tcx));

    // > If there is a unique bound from the containing type then that is the default
    // If there is a default object lifetime and the given region is lexically equal to it, elide it.
    match default {
        ObjectLifetimeDefault::Static => return region.kind() == ty::ReStatic,
        // FIXME(fmease): Don't compare lexically but respect de Bruijn indices etc. to handle shadowing correctly.
        ObjectLifetimeDefault::Arg(default) => {
            return region.get_name(tcx) == default.get_name(tcx);
        }
        // > If there is more than one bound from the containing type then an explicit bound must be specified
        // Due to ambiguity there is no default trait-object lifetime and thus elision is impossible.
        // Don't elide the lifetime.
        ObjectLifetimeDefault::Ambiguous => return false,
        // There is no meaningful bound. Further processing is needed...
        ObjectLifetimeDefault::Empty => {}
    }

    // > If neither of those rules apply, then the bounds on the trait are used:
    match *object_region_bounds(tcx, preds) {
        // > If the trait has no lifetime bounds, then the lifetime is inferred in expressions
        // > and is 'static outside of expressions.
        // FIXME: If we are in an expression context (i.e. fn bodies and const exprs) then the default is
        // `'_` and not `'static`. Only if we are in a non-expression one, the default is `'static`.
        // Note however that at the time of this writing it should be fine to disregard this subtlety
        // as we neither render const exprs faithfully anyway (hiding them in some places or using `_` instead)
        // nor show the contents of fn bodies.
        [] => region.kind() == ty::ReStatic,
        // > If the trait is defined with a single lifetime bound then that bound is used.
        // > If 'static is used for any lifetime bound then 'static is used.
        // FIXME(fmease): Don't compare lexically but respect de Bruijn indices etc. to handle shadowing correctly.
        [object_region] => object_region.get_name(tcx) == region.get_name(tcx),
        // There are several distinct trait regions and none are `'static`.
        // Due to ambiguity there is no default trait-object lifetime and thus elision is impossible.
        // Don't elide the lifetime.
        _ => false,
    }
}

#[derive(Debug)]
pub(crate) enum ContainerTy<'a, 'tcx> {
    Ref(ty::Region<'tcx>),
    Regular {
        ty: DefId,
        /// The arguments *have* to contain an arg for the self type if the corresponding generics
        /// contain a self type.
        args: ty::Binder<'tcx, &'a [ty::GenericArg<'tcx>]>,
        arg: usize,
    },
}

impl<'tcx> ContainerTy<'_, 'tcx> {
    fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> {
        match self {
            Self::Ref(region) => ObjectLifetimeDefault::Arg(region),
            Self::Regular { ty: container, args, arg: index } => {
                let (DefKind::Struct
                | DefKind::Union
                | DefKind::Enum
                | DefKind::TyAlias
                | DefKind::Trait) = tcx.def_kind(container)
                else {
                    return ObjectLifetimeDefault::Empty;
                };

                let generics = tcx.generics_of(container);
                debug_assert_eq!(generics.parent_count, 0);

                let param = generics.own_params[index].def_id;
                let default = tcx.object_lifetime_default(param);
                match default {
                    rbv::ObjectLifetimeDefault::Param(lifetime) => {
                        // The index is relative to the parent generics but since we don't have any,
                        // we don't need to translate it.
                        let index = generics.param_def_id_to_index[&lifetime];
                        let arg = args.skip_binder()[index as usize].expect_region();
                        ObjectLifetimeDefault::Arg(arg)
                    }
                    rbv::ObjectLifetimeDefault::Empty => ObjectLifetimeDefault::Empty,
                    rbv::ObjectLifetimeDefault::Static => ObjectLifetimeDefault::Static,
                    rbv::ObjectLifetimeDefault::Ambiguous => ObjectLifetimeDefault::Ambiguous,
                }
            }
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub(crate) enum ObjectLifetimeDefault<'tcx> {
    Empty,
    Static,
    Ambiguous,
    Arg(ty::Region<'tcx>),
}

#[instrument(level = "trace", skip(cx), ret)]
pub(crate) fn clean_middle_ty<'tcx>(
    bound_ty: ty::Binder<'tcx, Ty<'tcx>>,
    cx: &mut DocContext<'tcx>,
    parent_def_id: Option<DefId>,
    container: Option<ContainerTy<'_, 'tcx>>,
) -> Type {
    let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty);
    match *bound_ty.skip_binder().kind() {
        ty::Never => Primitive(PrimitiveType::Never),
        ty::Bool => Primitive(PrimitiveType::Bool),
        ty::Char => Primitive(PrimitiveType::Char),
        ty::Int(int_ty) => Primitive(int_ty.into()),
        ty::Uint(uint_ty) => Primitive(uint_ty.into()),
        ty::Float(float_ty) => Primitive(float_ty.into()),
        ty::Str => Primitive(PrimitiveType::Str),
        ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))),
        ty::Pat(ty, pat) => Type::Pat(
            Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)),
            format!("{pat:?}").into_boxed_str(),
        ),
        ty::Array(ty, n) => {
            let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n);
            let n = print_const(cx, n);
            Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into())
        }
        ty::RawPtr(ty, mutbl) => {
            RawPointer(mutbl, Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)))
        }
        ty::Ref(r, ty, mutbl) => BorrowedRef {
            lifetime: clean_middle_region(r, cx),
            mutability: mutbl,
            type_: Box::new(clean_middle_ty(
                bound_ty.rebind(ty),
                cx,
                None,
                Some(ContainerTy::Ref(r)),
            )),
        },
        ty::FnDef(..) | ty::FnPtr(..) => {
            // FIXME: should we merge the outer and inner binders somehow?
            let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
            let decl = clean_poly_fn_sig(cx, None, sig);
            let generic_params = clean_bound_vars(sig.bound_vars(), cx);

            BareFunction(Box::new(BareFunctionDecl {
                safety: sig.safety(),
                generic_params,
                decl,
                abi: sig.abi(),
            }))
        }
        ty::UnsafeBinder(inner) => {
            let generic_params = clean_bound_vars(inner.bound_vars(), cx);
            let ty = clean_middle_ty(inner.into(), cx, None, None);
            UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty }))
        }
        ty::Adt(def, args) => {
            let did = def.did();
            let kind = match def.adt_kind() {
                AdtKind::Struct => ItemType::Struct,
                AdtKind::Union => ItemType::Union,
                AdtKind::Enum => ItemType::Enum,
            };
            inline::record_extern_fqn(cx, did, kind);
            let path = clean_middle_path(cx, did, false, ThinVec::new(), bound_ty.rebind(args));
            Type::Path { path }
        }
        ty::Foreign(did) => {
            inline::record_extern_fqn(cx, did, ItemType::ForeignType);
            let path = clean_middle_path(
                cx,
                did,
                false,
                ThinVec::new(),
                ty::Binder::dummy(ty::GenericArgs::empty()),
            );
            Type::Path { path }
        }
        ty::Dynamic(obj, reg) => {
            // HACK: pick the first `did` as the `did` of the trait object. Someone
            // might want to implement "native" support for marker-trait-only
            // trait objects.
            let mut dids = obj.auto_traits();
            let did = obj
                .principal_def_id()
                .or_else(|| dids.next())
                .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?"));
            let args = match obj.principal() {
                Some(principal) => principal.map_bound(|p| p.args),
                // marker traits have no args.
                _ => ty::Binder::dummy(ty::GenericArgs::empty()),
            };

            inline::record_extern_fqn(cx, did, ItemType::Trait);

            let lifetime = clean_trait_object_lifetime_bound(reg, container, obj, cx.tcx);

            let mut bounds = dids
                .map(|did| {
                    let empty = ty::Binder::dummy(ty::GenericArgs::empty());
                    let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
                    inline::record_extern_fqn(cx, did, ItemType::Trait);
                    PolyTrait { trait_: path, generic_params: Vec::new() }
                })
                .collect::<Vec<_>>();

            let constraints = obj
                .projection_bounds()
                .map(|pb| AssocItemConstraint {
                    assoc: projection_to_path_segment(
                        pb.map_bound(|pb| {
                            pb.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)
                                .projection_term
                        }),
                        cx,
                    ),
                    kind: AssocItemConstraintKind::Equality {
                        term: clean_middle_term(pb.map_bound(|pb| pb.term), cx),
                    },
                })
                .collect();

            let late_bound_regions: FxIndexSet<_> = obj
                .iter()
                .flat_map(|pred| pred.bound_vars())
                .filter_map(|var| match var {
                    ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) => {
                        let name = cx.tcx.item_name(def_id);
                        if name != kw::UnderscoreLifetime {
                            Some(GenericParamDef::lifetime(def_id, name))
                        } else {
                            None
                        }
                    }
                    _ => None,
                })
                .collect();
            let late_bound_regions = late_bound_regions.into_iter().collect();

            let path = clean_middle_path(cx, did, false, constraints, args);
            bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions });

            DynTrait(bounds, lifetime)
        }
        ty::Tuple(t) => {
            Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None, None)).collect())
        }

        ty::Alias(ty::Projection, alias_ty @ ty::AliasTy { def_id, args, .. }) => {
            if cx.tcx.is_impl_trait_in_trait(def_id) {
                clean_middle_opaque_bounds(cx, def_id, args)
            } else {
                Type::QPath(Box::new(clean_projection(
                    bound_ty.rebind(alias_ty.into()),
                    cx,
                    parent_def_id,
                )))
            }
        }

        ty::Alias(ty::Inherent, alias_ty @ ty::AliasTy { def_id, .. }) => {
            let alias_ty = bound_ty.rebind(alias_ty);
            let self_type = clean_middle_ty(alias_ty.map_bound(|ty| ty.self_ty()), cx, None, None);

            Type::QPath(Box::new(QPathData {
                assoc: PathSegment {
                    name: cx.tcx.item_name(def_id),
                    args: GenericArgs::AngleBracketed {
                        args: clean_middle_generic_args(
                            cx,
                            alias_ty.map_bound(|ty| ty.args.as_slice()),
                            true,
                            def_id,
                        ),
                        constraints: Default::default(),
                    },
                },
                should_fully_qualify: false,
                self_type,
                trait_: None,
            }))
        }

        ty::Alias(ty::Free, ty::AliasTy { def_id, args, .. }) => {
            if cx.tcx.features().lazy_type_alias() {
                // Free type alias `data` represents the `type X` in `type X = Y`. If we need `Y`,
                // we need to use `type_of`.
                let path =
                    clean_middle_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(args));
                Type::Path { path }
            } else {
                let ty = cx.tcx.type_of(def_id).instantiate(cx.tcx, args);
                clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
            }
        }

        ty::Param(ref p) => {
            if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
                ImplTrait(bounds)
            } else if p.name == kw::SelfUpper {
                SelfTy
            } else {
                Generic(p.name)
            }
        }

        ty::Bound(_, ref ty) => match ty.kind {
            ty::BoundTyKind::Param(def_id) => Generic(cx.tcx.item_name(def_id)),
            ty::BoundTyKind::Anon => panic!("unexpected anonymous bound type variable"),
        },

        ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
            // If it's already in the same alias, don't get an infinite loop.
            if cx.current_type_aliases.contains_key(&def_id) {
                let path =
                    clean_middle_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(args));
                Type::Path { path }
            } else {
                *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                // by looking up the bounds associated with the def_id.
                let ty = clean_middle_opaque_bounds(cx, def_id, args);
                if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
                    *count -= 1;
                    if *count == 0 {
                        cx.current_type_aliases.remove(&def_id);
                    }
                }
                ty
            }
        }

        ty::Closure(..) => panic!("Closure"),
        ty::CoroutineClosure(..) => panic!("CoroutineClosure"),
        ty::Coroutine(..) => panic!("Coroutine"),
        ty::Placeholder(..) => panic!("Placeholder"),
        ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
        ty::Infer(..) => panic!("Infer"),

        ty::Error(_) => FatalError.raise(),
    }
}

fn clean_middle_opaque_bounds<'tcx>(
    cx: &mut DocContext<'tcx>,
    impl_trait_def_id: DefId,
    args: ty::GenericArgsRef<'tcx>,
) -> Type {
    let mut has_sized = false;

    let bounds: Vec<_> = cx
        .tcx
        .explicit_item_bounds(impl_trait_def_id)
        .iter_instantiated_copied(cx.tcx, args)
        .collect();

    let mut bounds = bounds
        .iter()
        .filter_map(|(bound, _)| {
            let bound_predicate = bound.kind();
            let trait_ref = match bound_predicate.skip_binder() {
                ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
                    return clean_middle_region(reg, cx).map(GenericBound::Outlives);
                }
                _ => return None,
            };

            // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized`
            // is shown and none of the new sizedness traits leak into documentation.
            if cx.tcx.is_lang_item(trait_ref.def_id(), LangItem::MetaSized) {
                return None;
            }

            if let Some(sized) = cx.tcx.lang_items().sized_trait()
                && trait_ref.def_id() == sized
            {
                has_sized = true;
                return None;
            }

            let bindings: ThinVec<_> = bounds
                .iter()
                .filter_map(|(bound, _)| {
                    let bound = bound.kind();
                    if let ty::ClauseKind::Projection(proj_pred) = bound.skip_binder()
                        && proj_pred.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder()
                    {
                        return Some(AssocItemConstraint {
                            assoc: projection_to_path_segment(
                                bound.rebind(proj_pred.projection_term),
                                cx,
                            ),
                            kind: AssocItemConstraintKind::Equality {
                                term: clean_middle_term(bound.rebind(proj_pred.term), cx),
                            },
                        });
                    }
                    None
                })
                .collect();

            Some(clean_poly_trait_ref_with_constraints(cx, trait_ref, bindings))
        })
        .collect::<Vec<_>>();

    if !has_sized {
        bounds.push(GenericBound::maybe_sized(cx));
    }

    // Move trait bounds to the front.
    bounds.sort_by_key(|b| !b.is_trait_bound());

    // Add back a `Sized` bound if there are no *trait* bounds remaining (incl. `?Sized`).
    // Since all potential trait bounds are at the front we can just check the first bound.
    if bounds.first().is_none_or(|b| !b.is_trait_bound()) {
        bounds.insert(0, GenericBound::sized(cx));
    }

    if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) {
        bounds.push(GenericBound::Use(
            args.iter()
                .map(|arg| match arg {
                    hir::PreciseCapturingArgKind::Lifetime(lt) => {
                        PreciseCapturingArg::Lifetime(Lifetime(*lt))
                    }
                    hir::PreciseCapturingArgKind::Param(param) => {
                        PreciseCapturingArg::Param(*param)
                    }
                })
                .collect(),
        ));
    }

    ImplTrait(bounds)
}

pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
    clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx)
}

pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) -> Item {
    clean_field_with_def_id(
        field.did,
        field.name,
        clean_middle_ty(
            ty::Binder::dummy(cx.tcx.type_of(field.did).instantiate_identity()),
            cx,
            Some(field.did),
            None,
        ),
        cx,
    )
}

pub(crate) fn clean_field_with_def_id(
    def_id: DefId,
    name: Symbol,
    ty: Type,
    cx: &mut DocContext<'_>,
) -> Item {
    Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx)
}

pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item {
    let discriminant = match variant.discr {
        ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
        ty::VariantDiscr::Relative(_) => None,
    };

    let kind = match variant.ctor_kind() {
        Some(CtorKind::Const) => VariantKind::CLike,
        Some(CtorKind::Fn) => VariantKind::Tuple(
            variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
        ),
        None => VariantKind::Struct(VariantStruct {
            fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(),
        }),
    };

    Item::from_def_id_and_parts(
        variant.def_id,
        Some(variant.name),
        VariantItem(Variant { kind, discriminant }),
        cx,
    )
}

pub(crate) fn clean_variant_def_with_args<'tcx>(
    variant: &ty::VariantDef,
    args: &GenericArgsRef<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> Item {
    let discriminant = match variant.discr {
        ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }),
        ty::VariantDiscr::Relative(_) => None,
    };

    use rustc_middle::traits::ObligationCause;
    use rustc_trait_selection::infer::TyCtxtInferExt;
    use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;

    let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
    let kind = match variant.ctor_kind() {
        Some(CtorKind::Const) => VariantKind::CLike,
        Some(CtorKind::Fn) => VariantKind::Tuple(
            variant
                .fields
                .iter()
                .map(|field| {
                    let ty = cx.tcx.type_of(field.did).instantiate(cx.tcx, args);

                    // normalize the type to only show concrete types
                    // note: we do not use try_normalize_erasing_regions since we
                    // do care about showing the regions
                    let ty = infcx
                        .at(&ObligationCause::dummy(), cx.param_env)
                        .query_normalize(ty)
                        .map(|normalized| normalized.value)
                        .unwrap_or(ty);

                    clean_field_with_def_id(
                        field.did,
                        field.name,
                        clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None),
                        cx,
                    )
                })
                .collect(),
        ),
        None => VariantKind::Struct(VariantStruct {
            fields: variant
                .fields
                .iter()
                .map(|field| {
                    let ty = cx.tcx.type_of(field.did).instantiate(cx.tcx, args);

                    // normalize the type to only show concrete types
                    // note: we do not use try_normalize_erasing_regions since we
                    // do care about showing the regions
                    let ty = infcx
                        .at(&ObligationCause::dummy(), cx.param_env)
                        .query_normalize(ty)
                        .map(|normalized| normalized.value)
                        .unwrap_or(ty);

                    clean_field_with_def_id(
                        field.did,
                        field.name,
                        clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None),
                        cx,
                    )
                })
                .collect(),
        }),
    };

    Item::from_def_id_and_parts(
        variant.def_id,
        Some(variant.name),
        VariantItem(Variant { kind, discriminant }),
        cx,
    )
}

fn clean_variant_data<'tcx>(
    variant: &hir::VariantData<'tcx>,
    disr_expr: &Option<&hir::AnonConst>,
    cx: &mut DocContext<'tcx>,
) -> Variant {
    let discriminant = disr_expr
        .map(|disr| Discriminant { expr: Some(disr.body), value: disr.def_id.to_def_id() });

    let kind = match variant {
        hir::VariantData::Struct { fields, .. } => VariantKind::Struct(VariantStruct {
            fields: fields.iter().map(|x| clean_field(x, cx)).collect(),
        }),
        hir::VariantData::Tuple(..) => {
            VariantKind::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect())
        }
        hir::VariantData::Unit(..) => VariantKind::CLike,
    };

    Variant { discriminant, kind }
}

fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
    Path {
        res: path.res,
        segments: path.segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
    }
}

fn clean_generic_args<'tcx>(
    generic_args: &hir::GenericArgs<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> GenericArgs {
    match generic_args.parenthesized {
        hir::GenericArgsParentheses::No => {
            let args = generic_args
                .args
                .iter()
                .map(|arg| match arg {
                    hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
                        GenericArg::Lifetime(clean_lifetime(lt, cx))
                    }
                    hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                    hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
                    hir::GenericArg::Const(ct) => {
                        GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct())))
                    }
                    hir::GenericArg::Infer(_inf) => GenericArg::Infer,
                })
                .collect();
            let constraints = generic_args
                .constraints
                .iter()
                .map(|c| clean_assoc_item_constraint(c, cx))
                .collect::<ThinVec<_>>();
            GenericArgs::AngleBracketed { args, constraints }
        }
        hir::GenericArgsParentheses::ParenSugar => {
            let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() else {
                bug!();
            };
            let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect();
            let output = match output.kind {
                hir::TyKind::Tup(&[]) => None,
                _ => Some(Box::new(clean_ty(output, cx))),
            };
            GenericArgs::Parenthesized { inputs, output }
        }
        hir::GenericArgsParentheses::ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
    }
}

fn clean_path_segment<'tcx>(
    path: &hir::PathSegment<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> PathSegment {
    PathSegment { name: path.ident.name, args: clean_generic_args(path.args(), cx) }
}

fn clean_bare_fn_ty<'tcx>(
    bare_fn: &hir::FnPtrTy<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> BareFunctionDecl {
    let (generic_params, decl) = enter_impl_trait(cx, |cx| {
        // NOTE: Generics must be cleaned before params.
        let generic_params = bare_fn
            .generic_params
            .iter()
            .filter(|p| !is_elided_lifetime(p))
            .map(|x| clean_generic_param(cx, None, x))
            .collect();
        // Since it's more conventional stylistically, elide the name of all params called `_`
        // unless there's at least one interestingly named param in which case don't elide any
        // name since mixing named and unnamed params is less legible.
        let filter = |ident: Option<Ident>| {
            ident.map(|ident| ident.name).filter(|&ident| ident != kw::Underscore)
        };
        let fallback =
            bare_fn.param_idents.iter().copied().find_map(filter).map(|_| kw::Underscore);
        let params = clean_params(cx, bare_fn.decl.inputs, bare_fn.param_idents, |ident| {
            filter(ident).or(fallback)
        });
        let decl = clean_fn_decl_with_params(cx, bare_fn.decl, None, params);
        (generic_params, decl)
    });
    BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params }
}

fn clean_unsafe_binder_ty<'tcx>(
    unsafe_binder_ty: &hir::UnsafeBinderTy<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> UnsafeBinderTy {
    let generic_params = unsafe_binder_ty
        .generic_params
        .iter()
        .filter(|p| !is_elided_lifetime(p))
        .map(|x| clean_generic_param(cx, None, x))
        .collect();
    let ty = clean_ty(unsafe_binder_ty.inner_ty, cx);
    UnsafeBinderTy { generic_params, ty }
}

pub(crate) fn reexport_chain(
    tcx: TyCtxt<'_>,
    import_def_id: LocalDefId,
    target_def_id: DefId,
) -> &[Reexport] {
    for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
        if child.res.opt_def_id() == Some(target_def_id)
            && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
        {
            return &child.reexport_chain;
        }
    }
    &[]
}

/// Collect attributes from the whole import chain.
fn get_all_import_attributes<'hir>(
    cx: &mut DocContext<'hir>,
    import_def_id: LocalDefId,
    target_def_id: DefId,
    is_inline: bool,
) -> Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)> {
    let mut attrs = Vec::new();
    let mut first = true;
    for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id)
        .iter()
        .flat_map(|reexport| reexport.id())
    {
        let import_attrs = inline::load_attrs(cx, def_id);
        if first {
            // This is the "original" reexport so we get all its attributes without filtering them.
            attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect();
            first = false;
        // We don't add attributes of an intermediate re-export if it has `#[doc(hidden)]`.
        } else if cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id) {
            add_without_unwanted_attributes(&mut attrs, import_attrs, is_inline, Some(def_id));
        }
    }
    attrs
}

fn filter_tokens_from_list(
    args_tokens: &TokenStream,
    should_retain: impl Fn(&TokenTree) -> bool,
) -> Vec<TokenTree> {
    let mut tokens = Vec::with_capacity(args_tokens.len());
    let mut skip_next_comma = false;
    for token in args_tokens.iter() {
        match token {
            TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => {
                skip_next_comma = false;
            }
            token if should_retain(token) => {
                skip_next_comma = false;
                tokens.push(token.clone());
            }
            _ => {
                skip_next_comma = true;
            }
        }
    }
    tokens
}

fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
    if is_inline {
        ident == sym::hidden || ident == sym::inline || ident == sym::no_inline
    } else {
        ident == sym::cfg
    }
}

/// Remove attributes from `normal` that should not be inherited by `use` re-export.
/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
    match args {
        hir::AttrArgs::Delimited(args) => {
            let tokens = filter_tokens_from_list(&args.tokens, |token| {
                !matches!(
                    token,
                    TokenTree::Token(
                        Token {
                            kind: TokenKind::Ident(
                                ident,
                                _,
                            ),
                            ..
                        },
                        _,
                    ) if filter_doc_attr_ident(*ident, is_inline),
                )
            });
            args.tokens = TokenStream::new(tokens);
        }
        hir::AttrArgs::Empty | hir::AttrArgs::Eq { .. } => {}
    }
}

/// When inlining items, we merge their attributes (and all the reexports attributes too) with the
/// final reexport. For example:
///
/// ```ignore (just an example)
/// #[doc(hidden, cfg(feature = "foo"))]
/// pub struct Foo;
///
/// #[doc(cfg(feature = "bar"))]
/// #[doc(hidden, no_inline)]
/// pub use Foo as Foo1;
///
/// #[doc(inline)]
/// pub use Foo2 as Bar;
/// ```
///
/// So `Bar` at the end will have both `cfg(feature = "...")`. However, we don't want to merge all
/// attributes so we filter out the following ones:
/// * `doc(inline)`
/// * `doc(no_inline)`
/// * `doc(hidden)`
fn add_without_unwanted_attributes<'hir>(
    attrs: &mut Vec<(Cow<'hir, hir::Attribute>, Option<DefId>)>,
    new_attrs: &'hir [hir::Attribute],
    is_inline: bool,
    import_parent: Option<DefId>,
) {
    for attr in new_attrs {
        if attr.is_doc_comment().is_some() {
            attrs.push((Cow::Borrowed(attr), import_parent));
            continue;
        }
        let mut attr = attr.clone();
        match attr {
            hir::Attribute::Unparsed(ref mut normal) if let [ident] = &*normal.path.segments => {
                let ident = ident.name;
                if ident == sym::doc {
                    filter_doc_attr(&mut normal.args, is_inline);
                    attrs.push((Cow::Owned(attr), import_parent));
                } else if is_inline || ident != sym::cfg_trace {
                    // If it's not a `cfg()` attribute, we keep it.
                    attrs.push((Cow::Owned(attr), import_parent));
                }
            }
            // FIXME: make sure to exclude `#[cfg_trace]` here when it is ported to the new parsers
            hir::Attribute::Parsed(..) => {
                attrs.push((Cow::Owned(attr), import_parent));
            }
            _ => {}
        }
    }
}

fn clean_maybe_renamed_item<'tcx>(
    cx: &mut DocContext<'tcx>,
    item: &hir::Item<'tcx>,
    renamed: Option<Symbol>,
    import_ids: &[LocalDefId],
) -> Vec<Item> {
    use hir::ItemKind;
    fn get_name(
        cx: &DocContext<'_>,
        item: &hir::Item<'_>,
        renamed: Option<Symbol>,
    ) -> Option<Symbol> {
        renamed.or_else(|| cx.tcx.hir_opt_name(item.hir_id()))
    }

    let def_id = item.owner_id.to_def_id();
    cx.with_param_env(def_id, |cx| {
        // These kinds of item either don't need a `name` or accept a `None` one so we handle them
        // before.
        match item.kind {
            ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
            ItemKind::Use(path, kind) => {
                return clean_use_statement(
                    item,
                    get_name(cx, item, renamed),
                    path,
                    kind,
                    cx,
                    &mut FxHashSet::default(),
                );
            }
            _ => {}
        }

        let mut name = get_name(cx, item, renamed).unwrap();

        let kind = match item.kind {
            ItemKind::Static(mutability, _, ty, body_id) => StaticItem(Static {
                type_: Box::new(clean_ty(ty, cx)),
                mutability,
                expr: Some(body_id),
            }),
            ItemKind::Const(_, generics, ty, rhs) => ConstantItem(Box::new(Constant {
                generics: clean_generics(generics, cx),
                type_: clean_ty(ty, cx),
                kind: clean_const_item_rhs(rhs, def_id),
            })),
            ItemKind::TyAlias(_, generics, ty) => {
                *cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
                let rustdoc_ty = clean_ty(ty, cx);
                let type_ =
                    clean_middle_ty(ty::Binder::dummy(lower_ty(cx.tcx, ty)), cx, None, None);
                let generics = clean_generics(generics, cx);
                if let Some(count) = cx.current_type_aliases.get_mut(&def_id) {
                    *count -= 1;
                    if *count == 0 {
                        cx.current_type_aliases.remove(&def_id);
                    }
                }

                let ty = cx.tcx.type_of(def_id).instantiate_identity();

                let mut ret = Vec::new();
                let inner_type = clean_ty_alias_inner_type(ty, cx, &mut ret);

                ret.push(generate_item_with_correct_attrs(
                    cx,
                    TypeAliasItem(Box::new(TypeAlias {
                        generics,
                        inner_type,
                        type_: rustdoc_ty,
                        item_type: Some(type_),
                    })),
                    item.owner_id.def_id.to_def_id(),
                    name,
                    import_ids,
                    renamed,
                ));
                return ret;
            }
            ItemKind::Enum(_, generics, def) => EnumItem(Enum {
                variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(),
                generics: clean_generics(generics, cx),
            }),
            ItemKind::TraitAlias(_, _, generics, bounds) => TraitAliasItem(TraitAlias {
                generics: clean_generics(generics, cx),
                bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
            }),
            ItemKind::Union(_, generics, variant_data) => UnionItem(Union {
                generics: clean_generics(generics, cx),
                fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
            }),
            ItemKind::Struct(_, generics, variant_data) => StructItem(Struct {
                ctor_kind: variant_data.ctor_kind(),
                generics: clean_generics(generics, cx),
                fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
            }),
            // FIXME: handle attributes and derives that aren't proc macros, and macros with
            // multiple kinds
            ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
                source: display_macro_source(cx, name, macro_def),
                macro_rules: macro_def.macro_rules,
            }),
            ItemKind::Macro(_, _, MacroKinds::ATTR) => {
                clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
            }
            ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
                clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
            }
            ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
            // proc macros can have a name set by attributes
            ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
                clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
            }
            ItemKind::Trait(_, _, _, _, generics, bounds, item_ids) => {
                let items = item_ids
                    .iter()
                    .map(|&ti| clean_trait_item(cx.tcx.hir_trait_item(ti), cx))
                    .collect();

                TraitItem(Box::new(Trait {
                    def_id,
                    items,
                    generics: clean_generics(generics, cx),
                    bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
                }))
            }
            ItemKind::ExternCrate(orig_name, _) => {
                return clean_extern_crate(item, name, orig_name, cx);
            }
            _ => span_bug!(item.span, "not yet converted"),
        };

        vec![generate_item_with_correct_attrs(
            cx,
            kind,
            item.owner_id.def_id.to_def_id(),
            name,
            import_ids,
            renamed,
        )]
    })
}

fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
    let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
    Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx)
}

fn clean_impl<'tcx>(
    impl_: &hir::Impl<'tcx>,
    def_id: LocalDefId,
    cx: &mut DocContext<'tcx>,
) -> Vec<Item> {
    let tcx = cx.tcx;
    let mut ret = Vec::new();
    let trait_ = impl_.of_trait.map(|t| clean_trait_ref(&t.trait_ref, cx));
    let items = impl_
        .items
        .iter()
        .map(|&ii| clean_impl_item(tcx.hir_impl_item(ii), cx))
        .collect::<Vec<_>>();

    // If this impl block is an implementation of the Deref trait, then we
    // need to try inlining the target's inherent impl blocks as well.
    if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
        build_deref_target_impls(cx, &items, &mut ret);
    }

    let for_ = clean_ty(impl_.self_ty, cx);
    let type_alias =
        for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) {
            DefKind::TyAlias => Some(clean_middle_ty(
                ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()),
                cx,
                Some(def_id.to_def_id()),
                None,
            )),
            _ => None,
        });
    let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
        let kind = ImplItem(Box::new(Impl {
            safety: match impl_.of_trait {
                Some(of_trait) => of_trait.safety,
                None => hir::Safety::Safe,
            },
            generics: clean_generics(impl_.generics, cx),
            trait_,
            for_,
            items,
            polarity: if impl_.of_trait.is_some() {
                tcx.impl_polarity(def_id)
            } else {
                ty::ImplPolarity::Positive
            },
            kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) {
                ImplKind::FakeVariadic
            } else {
                ImplKind::Normal
            },
        }));
        Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx)
    };
    if let Some(type_alias) = type_alias {
        ret.push(make_item(trait_.clone(), type_alias, items.clone()));
    }
    ret.push(make_item(trait_, for_, items));
    ret
}

fn clean_extern_crate<'tcx>(
    krate: &hir::Item<'tcx>,
    name: Symbol,
    orig_name: Option<Symbol>,
    cx: &mut DocContext<'tcx>,
) -> Vec<Item> {
    // this is the ID of the `extern crate` statement
    let cnum = cx.tcx.extern_mod_stmt_cnum(krate.owner_id.def_id).unwrap_or(LOCAL_CRATE);
    // this is the ID of the crate itself
    let crate_def_id = cnum.as_def_id();
    let attrs = cx.tcx.hir_attrs(krate.hir_id());
    let ty_vis = cx.tcx.visibility(krate.owner_id);
    let please_inline = ty_vis.is_public()
        && attrs.iter().any(|a| {
            a.has_name(sym::doc)
                && match a.meta_item_list() {
                    Some(l) => ast::attr::list_contains_name(&l, sym::inline),
                    None => false,
                }
        })
        && !cx.is_json_output();

    let krate_owner_def_id = krate.owner_id.def_id;

    if please_inline
        && let Some(items) = inline::try_inline(
            cx,
            Res::Def(DefKind::Mod, crate_def_id),
            name,
            Some((attrs, Some(krate_owner_def_id))),
            &mut Default::default(),
        )
    {
        return items;
    }

    vec![Item::from_def_id_and_parts(
        krate_owner_def_id.to_def_id(),
        Some(name),
        ExternCrateItem { src: orig_name },
        cx,
    )]
}

fn clean_use_statement<'tcx>(
    import: &hir::Item<'tcx>,
    name: Option<Symbol>,
    path: &hir::UsePath<'tcx>,
    kind: hir::UseKind,
    cx: &mut DocContext<'tcx>,
    inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Vec<Item> {
    let mut items = Vec::new();
    let hir::UsePath { segments, ref res, span } = *path;
    for res in res.present_items() {
        let path = hir::Path { segments, res, span };
        items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
    }
    items
}

fn clean_use_statement_inner<'tcx>(
    import: &hir::Item<'tcx>,
    name: Option<Symbol>,
    path: &hir::Path<'tcx>,
    kind: hir::UseKind,
    cx: &mut DocContext<'tcx>,
    inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Vec<Item> {
    if should_ignore_res(path.res) {
        return Vec::new();
    }
    // We need this comparison because some imports (for std types for example)
    // are "inserted" as well but directly by the compiler and they should not be
    // taken into account.
    if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
        return Vec::new();
    }

    let visibility = cx.tcx.visibility(import.owner_id);
    let attrs = cx.tcx.hir_attrs(import.hir_id());
    let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline);
    let pub_underscore = visibility.is_public() && name == Some(kw::Underscore);
    let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
    let import_def_id = import.owner_id.def_id;

    // The parent of the module in which this import resides. This
    // is the same as `current_mod` if that's already the top
    // level module.
    let parent_mod = cx.tcx.parent_module_from_def_id(current_mod.to_local_def_id());

    // This checks if the import can be seen from a higher level module.
    // In other words, it checks if the visibility is the equivalent of
    // `pub(super)` or higher. If the current module is the top level
    // module, there isn't really a parent module, which makes the results
    // meaningless. In this case, we make sure the answer is `false`.
    let is_visible_from_parent_mod =
        visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();

    if pub_underscore && let Some(ref inline) = inline_attr {
        struct_span_code_err!(
            cx.tcx.dcx(),
            inline.span(),
            E0780,
            "anonymous imports cannot be inlined"
        )
        .with_span_label(import.span, "anonymous import")
        .emit();
    }

    // We consider inlining the documentation of `pub use` statements, but we
    // forcefully don't inline if this is not public or if the
    // #[doc(no_inline)] attribute is present.
    // Don't inline doc(hidden) imports so they can be stripped at a later stage.
    let mut denied = cx.is_json_output()
        || !(visibility.is_public() || (cx.document_private() && is_visible_from_parent_mod))
        || pub_underscore
        || attrs.iter().any(|a| {
            a.has_name(sym::doc)
                && match a.meta_item_list() {
                    Some(l) => {
                        ast::attr::list_contains_name(&l, sym::no_inline)
                            || ast::attr::list_contains_name(&l, sym::hidden)
                    }
                    None => false,
                }
        });

    // Also check whether imports were asked to be inlined, in case we're trying to re-export a
    // crate in Rust 2018+
    let path = clean_path(path, cx);
    let inner = if kind == hir::UseKind::Glob {
        if !denied {
            let mut visited = DefIdSet::default();
            if let Some(items) = inline::try_inline_glob(
                cx,
                path.res,
                current_mod,
                &mut visited,
                inlined_names,
                import,
            ) {
                return items;
            }
        }
        Import::new_glob(resolve_use_source(cx, path), true)
    } else {
        let name = name.unwrap();
        if inline_attr.is_none()
            && let Res::Def(DefKind::Mod, did) = path.res
            && !did.is_local()
            && did.is_crate_root()
        {
            // if we're `pub use`ing an extern crate root, don't inline it unless we
            // were specifically asked for it
            denied = true;
        }
        if !denied
            && let Some(mut items) = inline::try_inline(
                cx,
                path.res,
                name,
                Some((attrs, Some(import_def_id))),
                &mut Default::default(),
            )
        {
            items.push(Item::from_def_id_and_parts(
                import_def_id.to_def_id(),
                None,
                ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
                cx,
            ));
            return items;
        }
        Import::new_simple(name, resolve_use_source(cx, path), true)
    };

    vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)]
}

fn clean_maybe_renamed_foreign_item<'tcx>(
    cx: &mut DocContext<'tcx>,
    item: &hir::ForeignItem<'tcx>,
    renamed: Option<Symbol>,
    import_id: Option<LocalDefId>,
) -> Item {
    let def_id = item.owner_id.to_def_id();
    cx.with_param_env(def_id, |cx| {
        let kind = match item.kind {
            hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem(
                clean_function(cx, &sig, generics, ParamsSrc::Idents(idents)),
                sig.header.safety(),
            ),
            hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
                Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None },
                safety,
            ),
            hir::ForeignItemKind::Type => ForeignTypeItem,
        };

        generate_item_with_correct_attrs(
            cx,
            kind,
            item.owner_id.def_id.to_def_id(),
            item.ident.name,
            import_id.as_slice(),
            renamed,
        )
    })
}

fn clean_assoc_item_constraint<'tcx>(
    constraint: &hir::AssocItemConstraint<'tcx>,
    cx: &mut DocContext<'tcx>,
) -> AssocItemConstraint {
    AssocItemConstraint {
        assoc: PathSegment {
            name: constraint.ident.name,
            args: clean_generic_args(constraint.gen_args, cx),
        },
        kind: match constraint.kind {
            hir::AssocItemConstraintKind::Equality { ref term } => {
                AssocItemConstraintKind::Equality { term: clean_hir_term(term, cx) }
            }
            hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound {
                bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(),
            },
        },
    }
}

fn clean_bound_vars<'tcx>(
    bound_vars: &ty::List<ty::BoundVariableKind>,
    cx: &mut DocContext<'tcx>,
) -> Vec<GenericParamDef> {
    bound_vars
        .into_iter()
        .filter_map(|var| match var {
            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) => {
                let name = cx.tcx.item_name(def_id);
                if name != kw::UnderscoreLifetime {
                    Some(GenericParamDef::lifetime(def_id, name))
                } else {
                    None
                }
            }
            ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => {
                let name = cx.tcx.item_name(def_id);
                Some(GenericParamDef {
                    name,
                    def_id,
                    kind: GenericParamDefKind::Type {
                        bounds: ThinVec::new(),
                        default: None,
                        synthetic: false,
                    },
                })
            }
            // FIXME(non_lifetime_binders): Support higher-ranked const parameters.
            ty::BoundVariableKind::Const => None,
            _ => None,
        })
        .collect()
}
