//! "Collection" is the process of determining the type and other external
//! details of each item in Rust. Collection is specifically concerned
//! with *inter-procedural* things -- for example, for a function
//! definition, collection will figure out the type and signature of the
//! function, but it will not visit the *body* of the function in any way,
//! nor examine type annotations on local variables (that's the job of
//! type *checking*).
//!
//! Collecting is ultimately defined by a bundle of queries that
//! inquire after various facts about the items in the crate (e.g.,
//! `type_of`, `generics_of`, `predicates_of`, etc). See the `provide` function
//! for the full set.
//!
//! At present, however, we do run collection across all items in the
//! crate as a kind of pass. This should eventually be factored away.

use std::assert_matches::assert_matches;
use std::cell::Cell;
use std::iter;
use std::ops::Bound;

use rustc_abi::{ExternAbi, Size};
use rustc_ast::Recovered;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{
    Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt};
use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{
    self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{
    FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
};
use tracing::{debug, instrument};

use crate::errors;
use crate::hir_ty_lowering::{
    FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason,
};

pub(crate) mod dump;
mod generics_of;
mod item_bounds;
mod predicates_of;
mod resolve_bound_vars;
mod type_of;

///////////////////////////////////////////////////////////////////////////

/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub(crate) fn provide(providers: &mut Providers) {
    resolve_bound_vars::provide(providers);
    *providers = Providers {
        type_of: type_of::type_of,
        type_of_opaque: type_of::type_of_opaque,
        type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
        type_alias_is_lazy: type_of::type_alias_is_lazy,
        item_bounds: item_bounds::item_bounds,
        explicit_item_bounds: item_bounds::explicit_item_bounds,
        item_self_bounds: item_bounds::item_self_bounds,
        explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
        item_non_self_bounds: item_bounds::item_non_self_bounds,
        impl_super_outlives: item_bounds::impl_super_outlives,
        generics_of: generics_of::generics_of,
        predicates_of: predicates_of::predicates_of,
        explicit_predicates_of: predicates_of::explicit_predicates_of,
        explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
        explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
        explicit_supertraits_containing_assoc_item:
            predicates_of::explicit_supertraits_containing_assoc_item,
        trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
        const_conditions: predicates_of::const_conditions,
        explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
        type_param_predicates: predicates_of::type_param_predicates,
        trait_def,
        adt_def,
        fn_sig,
        impl_trait_header,
        coroutine_kind,
        coroutine_for_closure,
        opaque_ty_origin,
        rendered_precise_capturing_args,
        const_param_default,
        anon_const_kind,
        const_of_item,
        ..*providers
    };
}

///////////////////////////////////////////////////////////////////////////

/// Context specific to some particular item. This is what implements [`HirTyLowerer`].
///
/// # `ItemCtxt` vs `FnCtxt`
///
/// `ItemCtxt` is primarily used to type-check item signatures and lower them
/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`].
/// It's also used for the bodies of items like structs where the body (the fields)
/// are just signatures.
///
/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
///
/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
/// while `FnCtxt` does do inference.
///
/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
///
/// # Trait predicates
///
/// `ItemCtxt` has information about the predicates that are defined
/// on the trait. Unfortunately, this predicate information is
/// available in various different forms at various points in the
/// process. So we can't just store a pointer to e.g., the HIR or the
/// parsed ty form, we have to be more flexible. To this end, the
/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
/// `probe_ty_param_bounds` requests, drawing the information from
/// the HIR (`hir::Generics`), recursively.
pub(crate) struct ItemCtxt<'tcx> {
    tcx: TyCtxt<'tcx>,
    item_def_id: LocalDefId,
    tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
}

///////////////////////////////////////////////////////////////////////////

#[derive(Default)]
pub(crate) struct HirPlaceholderCollector {
    pub spans: Vec<Span>,
    // If any of the spans points to a const infer var, then suppress any messages
    // that may try to turn that const infer into a type parameter.
    pub may_contain_const_infer: bool,
}

impl<'v> Visitor<'v> for HirPlaceholderCollector {
    fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
        self.spans.push(inf_span);

        if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
            self.may_contain_const_infer = true;
        }
    }
}

fn placeholder_type_error_diag<'cx, 'tcx>(
    cx: &'cx dyn HirTyLowerer<'tcx>,
    generics: Option<&hir::Generics<'_>>,
    placeholder_types: Vec<Span>,
    additional_spans: Vec<Span>,
    suggest: bool,
    hir_ty: Option<&hir::Ty<'_>>,
    kind: &'static str,
) -> Diag<'cx> {
    if placeholder_types.is_empty() {
        return bad_placeholder(cx, additional_spans, kind);
    }

    let params = generics.map(|g| g.params).unwrap_or_default();
    let type_name = params.next_type_param_name(None);
    let mut sugg: Vec<_> =
        placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();

    if let Some(generics) = generics {
        if let Some(span) = params.iter().find_map(|arg| match arg.name {
            hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
            _ => None,
        }) {
            // Account for `_` already present in cases like `struct S<_>(_);` and suggest
            // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
            sugg.push((span, (*type_name).to_string()));
        } else if let Some(span) = generics.span_for_param_suggestion() {
            // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
            sugg.push((span, format!(", {type_name}")));
        } else {
            sugg.push((generics.span, format!("<{type_name}>")));
        }
    }

    let mut err =
        bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);

    // Suggest, but only if it is not a function in const or static
    if suggest {
        let mut is_fn = false;
        let mut is_const_or_static = false;

        if let Some(hir_ty) = hir_ty
            && let hir::TyKind::FnPtr(_) = hir_ty.kind
        {
            is_fn = true;

            // Check if parent is const or static
            is_const_or_static = matches!(
                cx.tcx().parent_hir_node(hir_ty.hir_id),
                Node::Item(&hir::Item {
                    kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
                    ..
                }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
                    | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
            );
        }

        // if function is wrapped around a const or static,
        // then don't show the suggestion
        if !(is_fn && is_const_or_static) {
            err.multipart_suggestion(
                "use type parameters instead",
                sugg,
                Applicability::HasPlaceholders,
            );
        }
    }

    err
}

///////////////////////////////////////////////////////////////////////////
// Utility types and common code for the above passes.

fn bad_placeholder<'cx, 'tcx>(
    cx: &'cx dyn HirTyLowerer<'tcx>,
    mut spans: Vec<Span>,
    kind: &'static str,
) -> Diag<'cx> {
    let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };

    spans.sort();
    cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
}

impl<'tcx> ItemCtxt<'tcx> {
    pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
        ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
    }

    pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
        self.lowerer().lower_ty(hir_ty)
    }

    pub(crate) fn hir_id(&self) -> hir::HirId {
        self.tcx.local_def_id_to_hir_id(self.item_def_id)
    }

    pub(crate) fn node(&self) -> hir::Node<'tcx> {
        self.tcx.hir_node(self.hir_id())
    }

    fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
        match self.tainted_by_errors.get() {
            Some(err) => Err(err),
            None => Ok(()),
        }
    }

    fn report_placeholder_type_error(
        &self,
        placeholder_types: Vec<Span>,
        infer_replacements: Vec<(Span, String)>,
    ) -> ErrorGuaranteed {
        let node = self.tcx.hir_node_by_def_id(self.item_def_id);
        let generics = node.generics();
        let kind_id = match node {
            Node::GenericParam(_) | Node::WherePredicate(_) | Node::Field(_) => {
                self.tcx.local_parent(self.item_def_id)
            }
            _ => self.item_def_id,
        };
        let kind = self.tcx.def_descr(kind_id.into());
        let mut diag = placeholder_type_error_diag(
            self,
            generics,
            placeholder_types,
            infer_replacements.iter().map(|&(span, _)| span).collect(),
            false,
            None,
            kind,
        );
        if !infer_replacements.is_empty() {
            diag.multipart_suggestion(
                format!(
                    "try replacing `_` with the type{} in the corresponding trait method \
                        signature",
                    rustc_errors::pluralize!(infer_replacements.len()),
                ),
                infer_replacements,
                Applicability::MachineApplicable,
            );
        }

        diag.emit()
    }
}

impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn dcx(&self) -> DiagCtxtHandle<'_> {
        self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
    }

    fn item_def_id(&self) -> LocalDefId {
        self.item_def_id
    }

    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
        if let RegionInferReason::ObjectLifetimeDefault = reason {
            let e = struct_span_code_err!(
                self.dcx(),
                span,
                E0228,
                "the lifetime bound for this object type cannot be deduced \
                from context; please supply an explicit bound"
            )
            .emit();
            ty::Region::new_error(self.tcx(), e)
        } else {
            // This indicates an illegal lifetime in a non-assoc-trait position
            ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
        }
    }

    fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
        if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) {
            self.report_placeholder_type_error(vec![span], vec![]);
        }
        Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
    }

    fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
        self.report_placeholder_type_error(vec![span], vec![]);
        ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
    }

    fn register_trait_ascription_bounds(
        &self,
        _: Vec<(ty::Clause<'tcx>, Span)>,
        _: HirId,
        span: Span,
    ) {
        self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
    }

    fn probe_ty_param_bounds(
        &self,
        span: Span,
        def_id: LocalDefId,
        assoc_ident: Ident,
    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
        self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
    }

    #[instrument(level = "debug", skip(self, _span), ret)]
    fn select_inherent_assoc_candidates(
        &self,
        _span: Span,
        self_ty: Ty<'tcx>,
        candidates: Vec<InherentAssocCandidate>,
    ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
        assert!(!self_ty.has_infer());

        // We don't just call the normal normalization routine here as we can't provide the
        // correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
        // the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
        // this just to make resolution a little bit smarter.
        let self_ty = self.tcx.expand_free_alias_tys(self_ty);
        debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);

        let candidates = candidates
            .into_iter()
            .filter(|&InherentAssocCandidate { impl_, .. }| {
                let impl_ty = self.tcx().type_of(impl_).instantiate_identity();

                // See comment on doing this operation for `self_ty`
                let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
                debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);

                // We treat parameters in the self ty as rigid and parameters in the impl ty as infers
                // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
                // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
                //
                // We don't really care about a depth limit here because we're only working with user-written
                // types and if they wrote a type that would take hours to walk then that's kind of on them. On
                // the other hand the default depth limit is relatively low and could realistically be hit by
                // users in normal cases.
                //
                // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
                // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
                // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
                //
                // Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
                // resolution, but it probably won't come up in practice and it would be backwards compatible
                // to switch over to doing that.
                ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
                    self_ty,
                    impl_ty,
                    usize::MAX,
                )
            })
            .collect();

        (candidates, vec![])
    }

    fn lower_assoc_item_path(
        &self,
        span: Span,
        item_def_id: DefId,
        item_segment: &rustc_hir::PathSegment<'tcx>,
        poly_trait_ref: ty::PolyTraitRef<'tcx>,
    ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
            let item_args = self.lowerer().lower_generic_args_of_assoc_item(
                span,
                item_def_id,
                item_segment,
                trait_ref.args,
            );
            Ok((item_def_id, item_args))
        } else {
            // There are no late-bound regions; we can just ignore the binder.
            let (mut mpart_sugg, mut inferred_sugg) = (None, None);
            let mut bound = String::new();

            match self.node() {
                hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
                    let item = self
                        .tcx
                        .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
                    match &item.kind {
                        hir::ItemKind::Enum(_, generics, _)
                        | hir::ItemKind::Struct(_, generics, _)
                        | hir::ItemKind::Union(_, generics, _) => {
                            let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
                            let (lt_sp, sugg) = match generics.params {
                                [] => (generics.span, format!("<{lt_name}>")),
                                [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
                            };
                            mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
                                fspan: lt_sp,
                                first: sugg,
                                sspan: span.with_hi(item_segment.ident.span.lo()),
                                second: format!(
                                    "{}::",
                                    // Replace the existing lifetimes with a new named lifetime.
                                    self.tcx.instantiate_bound_regions_uncached(
                                        poly_trait_ref,
                                        |_| {
                                            ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
                                                index: 0,
                                                name: Symbol::intern(&lt_name),
                                            })
                                        }
                                    ),
                                ),
                            });
                        }
                        _ => {}
                    }
                }
                hir::Node::Item(hir::Item {
                    kind:
                        hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
                    ..
                }) => {}
                hir::Node::Item(_)
                | hir::Node::ForeignItem(_)
                | hir::Node::TraitItem(_)
                | hir::Node::ImplItem(_) => {
                    inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
                    bound = format!(
                        "{}::",
                        // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
                        self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
                    );
                }
                _ => {}
            }

            Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
                span,
                inferred_sugg,
                bound,
                mpart_sugg,
                what: self.tcx.def_descr(item_def_id),
            }))
        }
    }

    fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
        // FIXME(#103640): Should we handle the case where `ty` is a projection?
        ty.ty_adt_def()
    }

    fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
        // There's no place to record types from signatures?
    }

    fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
        None
    }

    fn lower_fn_sig(
        &self,
        decl: &hir::FnDecl<'tcx>,
        _generics: Option<&hir::Generics<'_>>,
        hir_id: rustc_hir::HirId,
        _hir_ty: Option<&hir::Ty<'_>>,
    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
        let tcx = self.tcx();

        let mut infer_replacements = vec![];

        let input_tys = decl
            .inputs
            .iter()
            .enumerate()
            .map(|(i, a)| {
                if let hir::TyKind::Infer(()) = a.kind
                    && let Some(suggested_ty) =
                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
                {
                    infer_replacements.push((a.span, suggested_ty.to_string()));
                    return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
                }

                self.lowerer().lower_ty(a)
            })
            .collect();

        let output_ty = match decl.output {
            hir::FnRetTy::Return(output) => {
                if let hir::TyKind::Infer(()) = output.kind
                    && let Some(suggested_ty) =
                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
                {
                    infer_replacements.push((output.span, suggested_ty.to_string()));
                    Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
                } else {
                    self.lower_ty(output)
                }
            }
            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
        };

        if !infer_replacements.is_empty() {
            self.report_placeholder_type_error(vec![], infer_replacements);
        }
        (input_tys, output_ty)
    }

    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
        hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
    }
}

/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
fn get_new_lifetime_name<'tcx>(
    tcx: TyCtxt<'tcx>,
    poly_trait_ref: ty::PolyTraitRef<'tcx>,
    generics: &hir::Generics<'tcx>,
) -> String {
    let existing_lifetimes = tcx
        .collect_referenced_late_bound_regions(poly_trait_ref)
        .into_iter()
        .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
        .chain(generics.params.iter().filter_map(|param| {
            if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
                Some(param.name.ident().as_str().to_string())
            } else {
                None
            }
        }))
        .collect::<FxHashSet<String>>();

    let a_to_z_repeat_n = |n| {
        (b'a'..=b'z').map(move |c| {
            let mut s = '\''.to_string();
            s.extend(std::iter::repeat_n(char::from(c), n));
            s
        })
    };

    // If all single char lifetime names are present, we wrap around and double the chars.
    (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
}

pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
    tcx.ensure_ok().generics_of(def_id);
    tcx.ensure_ok().type_of(def_id);
    tcx.ensure_ok().predicates_of(def_id);
}

pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: LocalDefId) {
    let def = tcx.adt_def(def_id);
    let repr_type = def.repr().discr_type();
    let initial = repr_type.initial_discriminant(tcx);
    let mut prev_discr = None::<Discr<'_>>;
    // Some of the logic below relies on `i128` being able to hold all c_int and c_uint values.
    assert!(tcx.sess.target.c_int_width < 128);
    let mut min_discr = i128::MAX;
    let mut max_discr = i128::MIN;

    // fill the discriminant values and field types
    for variant in def.variants() {
        let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
        let cur_discr = if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
            def.eval_explicit_discr(tcx, const_def_id).ok()
        } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
            Some(discr)
        } else {
            let span = tcx.def_span(variant.def_id);
            tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
                span,
                discr: prev_discr.unwrap().to_string(),
                item_name: tcx.item_ident(variant.def_id),
                wrapped_discr: wrapped_discr.to_string(),
            });
            None
        }
        .unwrap_or(wrapped_discr);

        if def.repr().c() {
            let c_int = Size::from_bits(tcx.sess.target.c_int_width);
            let c_uint_max = i128::try_from(c_int.unsigned_int_max()).unwrap();
            // c_int is a signed type, so get a proper signed version of the discriminant
            let discr_size = cur_discr.ty.int_size_and_signed(tcx).0;
            let discr_val = discr_size.sign_extend(cur_discr.val);
            min_discr = min_discr.min(discr_val);
            max_discr = max_discr.max(discr_val);

            // The discriminant range must either fit into c_int or c_uint.
            if !(min_discr >= c_int.signed_int_min() && max_discr <= c_int.signed_int_max())
                && !(min_discr >= 0 && max_discr <= c_uint_max)
            {
                let span = tcx.def_span(variant.def_id);
                let msg = if discr_val < c_int.signed_int_min() || discr_val > c_uint_max {
                    "`repr(C)` enum discriminant does not fit into C `int` nor into C `unsigned int`"
                } else if discr_val < 0 {
                    "`repr(C)` enum discriminant does not fit into C `unsigned int`, and a previous discriminant does not fit into C `int`"
                } else {
                    "`repr(C)` enum discriminant does not fit into C `int`, and a previous discriminant does not fit into C `unsigned int`"
                };
                tcx.node_span_lint(
                    rustc_session::lint::builtin::REPR_C_ENUMS_LARGER_THAN_INT,
                    tcx.local_def_id_to_hir_id(def_id),
                    span,
                    |d| {
                        d.primary_message(msg)
                        .note("`repr(C)` enums with big discriminants are non-portable, and their size in Rust might not match their size in C")
                        .help("use `repr($int_ty)` instead to explicitly set the size of this enum");
                    }
                );
            }
        }

        prev_discr = Some(cur_discr);

        for f in &variant.fields {
            tcx.ensure_ok().generics_of(f.did);
            tcx.ensure_ok().type_of(f.did);
            tcx.ensure_ok().predicates_of(f.did);
        }

        // Lower the ctor, if any. This also registers the variant as an item.
        if let Some(ctor_def_id) = variant.ctor_def_id() {
            lower_variant_ctor(tcx, ctor_def_id.expect_local());
        }
    }
}

#[derive(Clone, Copy)]
struct NestedSpan {
    span: Span,
    nested_field_span: Span,
}

impl NestedSpan {
    fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
        errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
    }
}

#[derive(Clone, Copy)]
enum FieldDeclSpan {
    NotNested(Span),
    Nested(NestedSpan),
}

impl From<Span> for FieldDeclSpan {
    fn from(span: Span) -> Self {
        Self::NotNested(span)
    }
}

impl From<NestedSpan> for FieldDeclSpan {
    fn from(span: NestedSpan) -> Self {
        Self::Nested(span)
    }
}

struct FieldUniquenessCheckContext<'tcx> {
    tcx: TyCtxt<'tcx>,
    seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
}

impl<'tcx> FieldUniquenessCheckContext<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx, seen_fields: FxIndexMap::default() }
    }

    /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
    fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
        use FieldDeclSpan::*;
        let field_name = field_name.normalize_to_macros_2_0();
        match (field_decl, self.seen_fields.get(&field_name).copied()) {
            (NotNested(span), Some(NotNested(prev_span))) => {
                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
                    field_name,
                    span,
                    prev_span,
                });
            }
            (NotNested(span), Some(Nested(prev))) => {
                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
                    field_name,
                    span,
                    prev_span: prev.span,
                    prev_nested_field_span: prev.nested_field_span,
                    prev_help: prev.to_field_already_declared_nested_help(),
                });
            }
            (
                Nested(current @ NestedSpan { span, nested_field_span, .. }),
                Some(NotNested(prev_span)),
            ) => {
                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
                    field_name,
                    span,
                    nested_field_span,
                    help: current.to_field_already_declared_nested_help(),
                    prev_span,
                });
            }
            (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
                    field_name,
                    span,
                    nested_field_span,
                    help: current.to_field_already_declared_nested_help(),
                    prev_span: prev.span,
                    prev_nested_field_span: prev.nested_field_span,
                    prev_help: prev.to_field_already_declared_nested_help(),
                });
            }
            (field_decl, None) => {
                self.seen_fields.insert(field_name, field_decl);
            }
        }
    }
}

fn lower_variant<'tcx>(
    tcx: TyCtxt<'tcx>,
    variant_did: Option<LocalDefId>,
    ident: Ident,
    discr: ty::VariantDiscr,
    def: &hir::VariantData<'tcx>,
    adt_kind: ty::AdtKind,
    parent_did: LocalDefId,
) -> ty::VariantDef {
    let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
    let fields = def
        .fields()
        .iter()
        .inspect(|field| {
            field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
        })
        .map(|f| ty::FieldDef {
            did: f.def_id.to_def_id(),
            name: f.ident.name,
            vis: tcx.visibility(f.def_id),
            safety: f.safety,
            value: f.default.map(|v| v.def_id.to_def_id()),
        })
        .collect();
    let recovered = match def {
        hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
        _ => None,
    };
    ty::VariantDef::new(
        ident.name,
        variant_did.map(LocalDefId::to_def_id),
        def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
        discr,
        fields,
        parent_did.to_def_id(),
        recovered,
        adt_kind == AdtKind::Struct
            && find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
            || variant_did.is_some_and(|variant_did| {
                find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
            }),
    )
}

fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
    use rustc_hir::*;

    let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
        bug!("expected ADT to be an item");
    };

    let repr = tcx.repr_options_of_def(def_id);
    let (kind, variants) = match &item.kind {
        ItemKind::Enum(_, _, def) => {
            let mut distance_from_explicit = 0;
            let variants = def
                .variants
                .iter()
                .map(|v| {
                    let discr = if let Some(e) = &v.disr_expr {
                        distance_from_explicit = 0;
                        ty::VariantDiscr::Explicit(e.def_id.to_def_id())
                    } else {
                        ty::VariantDiscr::Relative(distance_from_explicit)
                    };
                    distance_from_explicit += 1;

                    lower_variant(
                        tcx,
                        Some(v.def_id),
                        v.ident,
                        discr,
                        &v.data,
                        AdtKind::Enum,
                        def_id,
                    )
                })
                .collect();

            (AdtKind::Enum, variants)
        }
        ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
            let adt_kind = match item.kind {
                ItemKind::Struct(..) => AdtKind::Struct,
                _ => AdtKind::Union,
            };
            let variants = std::iter::once(lower_variant(
                tcx,
                None,
                *ident,
                ty::VariantDiscr::Relative(0),
                def,
                adt_kind,
                def_id,
            ))
            .collect();

            (adt_kind, variants)
        }
        _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
    };
    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
}

fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
    let item = tcx.hir_expect_item(def_id);

    let (constness, is_alias, is_auto, safety) = match item.kind {
        hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
            (constness, false, is_auto == hir::IsAuto::Yes, safety)
        }
        hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe),
        _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
    };

    let attrs = tcx.get_all_attrs(def_id);

    let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_));
    if paren_sugar && !tcx.features().unboxed_closures() {
        tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
    }

    // Only regular traits can be marker.
    let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_));

    let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_));
    let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental);

    let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
        attrs,
        AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
    )
    .unwrap_or([false; 2]);

    let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) {
        ty::trait_def::TraitSpecializationKind::Marker
    } else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) {
        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
    } else {
        ty::trait_def::TraitSpecializationKind::None
    };
    let must_implement_one_of = attrs
        .iter()
        .find(|attr| attr.has_name(sym::rustc_must_implement_one_of))
        // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
        // and that they are all identifiers
        .and_then(|attr| match attr.meta_item_list() {
            Some(items) if items.len() < 2 => {
                tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });

                None
            }
            Some(items) => items
                .into_iter()
                .map(|item| item.ident().ok_or(item.span()))
                .collect::<Result<Box<[_]>, _>>()
                .map_err(|span| {
                    tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
                })
                .ok()
                .zip(Some(attr.span())),
            // Error is reported by `rustc_attr!`
            None => None,
        })
        // Check that all arguments of `#[rustc_must_implement_one_of]` reference
        // functions in the trait with default implementations
        .and_then(|(list, attr_span)| {
            let errors = list.iter().filter_map(|ident| {
                let item = tcx
                    .associated_items(def_id)
                    .filter_by_name_unhygienic(ident.name)
                    .find(|item| item.ident(tcx) == *ident);

                match item {
                    Some(item) if matches!(item.kind, ty::AssocKind::Fn { .. }) => {
                        if !item.defaultness(tcx).has_value() {
                            tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
                                span: tcx.def_span(item.def_id),
                                note_span: attr_span,
                            });

                            return Some(());
                        }

                        return None;
                    }
                    Some(item) => {
                        tcx.dcx().emit_err(errors::MustImplementNotFunction {
                            span: tcx.def_span(item.def_id),
                            span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
                            note: errors::MustImplementNotFunctionNote {},
                        });
                    }
                    None => {
                        tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
                    }
                }

                Some(())
            });

            (errors.count() == 0).then_some(list)
        })
        // Check for duplicates
        .and_then(|list| {
            let mut set: UnordMap<Symbol, Span> = Default::default();
            let mut no_dups = true;

            for ident in &*list {
                if let Some(dup) = set.insert(ident.name, ident.span) {
                    tcx.dcx()
                        .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });

                    no_dups = false;
                }
            }

            no_dups.then_some(list)
        });

    let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
    let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));

    ty::TraitDef {
        def_id: def_id.to_def_id(),
        safety,
        constness,
        paren_sugar,
        has_auto_impl: is_auto,
        is_marker,
        is_coinductive: rustc_coinductive || is_auto,
        is_fundamental,
        skip_array_during_method_dispatch,
        skip_boxed_slice_during_method_dispatch,
        specialization_kind,
        must_implement_one_of,
        implement_via_object,
        deny_explicit_impl,
    }
}

#[instrument(level = "debug", skip(tcx), ret)]
fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
    use rustc_hir::Node::*;
    use rustc_hir::*;

    let hir_id = tcx.local_def_id_to_hir_id(def_id);

    let icx = ItemCtxt::new(tcx, def_id);

    let output = match tcx.hir_node(hir_id) {
        TraitItem(hir::TraitItem {
            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
            generics,
            ..
        })
        | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
            lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
        }

        ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
            // Do not try to infer the return type for a impl method coming from a trait
            if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
                && i.of_trait.is_some()
            {
                icx.lowerer().lower_fn_ty(
                    hir_id,
                    sig.header.safety(),
                    sig.header.abi,
                    sig.decl,
                    Some(generics),
                    None,
                )
            } else {
                lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
            }
        }

        TraitItem(hir::TraitItem {
            kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
            generics,
            ..
        }) => icx.lowerer().lower_fn_ty(
            hir_id,
            header.safety(),
            header.abi,
            decl,
            Some(generics),
            None,
        ),

        ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
            let abi = tcx.hir_get_foreign_abi(hir_id);
            compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
        }

        Ctor(data) => {
            assert_matches!(data.ctor(), Some(_));
            let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
            let ty = tcx.type_of(adt_def_id).instantiate_identity();
            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
            // constructors for structs with `layout_scalar_valid_range` are unsafe to call
            let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
                (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
                _ => hir::Safety::Unsafe,
            };
            ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
        }

        Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
            // Closure signatures are not like other function
            // signatures and cannot be accessed through `fn_sig`. For
            // example, a closure signature excludes the `self`
            // argument. In any case they are embedded within the
            // closure type as part of the `ClosureArgs`.
            //
            // To get the signature of a closure, you should use the
            // `sig` method on the `ClosureArgs`:
            //
            //    args.as_closure().sig(def_id, tcx)
            bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
        }

        x => {
            bug!("unexpected sort of node in fn_sig(): {:?}", x);
        }
    };
    ty::EarlyBinder::bind(output)
}

fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
    icx: &ItemCtxt<'tcx>,
    sig: &'tcx hir::FnSig<'tcx>,
    generics: &'tcx hir::Generics<'tcx>,
    def_id: LocalDefId,
) -> ty::PolyFnSig<'tcx> {
    if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
        return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
    }

    icx.lowerer().lower_fn_ty(
        icx.tcx().local_def_id_to_hir_id(def_id),
        sig.header.safety(),
        sig.header.abi,
        sig.decl,
        Some(generics),
        None,
    )
}

fn recover_infer_ret_ty<'tcx>(
    icx: &ItemCtxt<'tcx>,
    infer_ret_ty: &'tcx hir::Ty<'tcx>,
    generics: &'tcx hir::Generics<'tcx>,
    def_id: LocalDefId,
) -> ty::PolyFnSig<'tcx> {
    let tcx = icx.tcx;
    let hir_id = tcx.local_def_id_to_hir_id(def_id);

    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];

    // Typeck doesn't expect erased regions to be returned from `type_of`.
    // This is a heuristic approach. If the scope has region parameters,
    // we should change fn_sig's lifetime from `ReErased` to `ReError`,
    // otherwise to `ReStatic`.
    let has_region_params = generics.params.iter().any(|param| match param.kind {
        GenericParamKind::Lifetime { .. } => true,
        _ => false,
    });
    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
        ty::ReErased => {
            if has_region_params {
                ty::Region::new_error_with_message(
                    tcx,
                    DUMMY_SP,
                    "erased region is not allowed here in return type",
                )
            } else {
                tcx.lifetimes.re_static
            }
        }
        _ => r,
    });

    let mut visitor = HirPlaceholderCollector::default();
    visitor.visit_ty_unambig(infer_ret_ty);

    let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
    let ret_ty = fn_sig.output();

    // Don't leak types into signatures unless they're nameable!
    // For example, if a function returns itself, we don't want that
    // recursive function definition to leak out into the fn sig.
    let mut recovered_ret_ty = None;
    if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
        diag.span_suggestion_verbose(
            infer_ret_ty.span,
            "replace with the correct return type",
            suggestable_ret_ty,
            Applicability::MachineApplicable,
        );
        recovered_ret_ty = Some(suggestable_ret_ty);
    } else if let Some(sugg) = suggest_impl_trait(
        &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
        tcx.param_env(def_id),
        ret_ty,
    ) {
        diag.span_suggestion_verbose(
            infer_ret_ty.span,
            "replace with an appropriate return type",
            sugg,
            Applicability::MachineApplicable,
        );
    } else if ret_ty.is_closure() {
        diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
    }

    // Also note how `Fn` traits work just in case!
    if ret_ty.is_closure() {
        diag.note(
            "for more information on `Fn` traits and closure types, see \
                     https://doc.rust-lang.org/book/ch13-01-closures.html",
        );
    }
    let guar = diag.emit();
    ty::Binder::dummy(tcx.mk_fn_sig(
        fn_sig.inputs().iter().copied(),
        recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
        fn_sig.c_variadic,
        fn_sig.safety,
        fn_sig.abi,
    ))
}

pub fn suggest_impl_trait<'tcx>(
    infcx: &InferCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    ret_ty: Ty<'tcx>,
) -> Option<String> {
    let format_as_assoc: fn(_, _, _, _, _) -> _ =
        |tcx: TyCtxt<'tcx>,
         _: ty::GenericArgsRef<'tcx>,
         trait_def_id: DefId,
         assoc_item_def_id: DefId,
         item_ty: Ty<'tcx>| {
            let trait_name = tcx.item_name(trait_def_id);
            let assoc_name = tcx.item_name(assoc_item_def_id);
            Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
        };
    let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
        |tcx: TyCtxt<'tcx>,
         args: ty::GenericArgsRef<'tcx>,
         trait_def_id: DefId,
         _: DefId,
         item_ty: Ty<'tcx>| {
            let trait_name = tcx.item_name(trait_def_id);
            let args_tuple = args.type_at(1);
            let ty::Tuple(types) = *args_tuple.kind() else {
                return None;
            };
            let types = types.make_suggestable(tcx, false, None)?;
            let maybe_ret =
                if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
            Some(format!(
                "impl {trait_name}({}){maybe_ret}",
                types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
            ))
        };

    for (trait_def_id, assoc_item_def_id, formatter) in [
        (
            infcx.tcx.get_diagnostic_item(sym::Iterator),
            infcx.tcx.get_diagnostic_item(sym::IteratorItem),
            format_as_assoc,
        ),
        (
            infcx.tcx.lang_items().future_trait(),
            infcx.tcx.lang_items().future_output(),
            format_as_assoc,
        ),
        (
            infcx.tcx.lang_items().async_fn_trait(),
            infcx.tcx.lang_items().async_fn_once_output(),
            format_as_parenthesized,
        ),
        (
            infcx.tcx.lang_items().async_fn_mut_trait(),
            infcx.tcx.lang_items().async_fn_once_output(),
            format_as_parenthesized,
        ),
        (
            infcx.tcx.lang_items().async_fn_once_trait(),
            infcx.tcx.lang_items().async_fn_once_output(),
            format_as_parenthesized,
        ),
        (
            infcx.tcx.lang_items().fn_trait(),
            infcx.tcx.lang_items().fn_once_output(),
            format_as_parenthesized,
        ),
        (
            infcx.tcx.lang_items().fn_mut_trait(),
            infcx.tcx.lang_items().fn_once_output(),
            format_as_parenthesized,
        ),
        (
            infcx.tcx.lang_items().fn_once_trait(),
            infcx.tcx.lang_items().fn_once_output(),
            format_as_parenthesized,
        ),
    ] {
        let Some(trait_def_id) = trait_def_id else {
            continue;
        };
        let Some(assoc_item_def_id) = assoc_item_def_id else {
            continue;
        };
        if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
            continue;
        }
        let sugg = infcx.probe(|_| {
            let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
                if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
            });
            if !infcx
                .type_implements_trait(trait_def_id, args, param_env)
                .must_apply_modulo_regions()
            {
                return None;
            }
            let ocx = ObligationCtxt::new(&infcx);
            let item_ty = ocx.normalize(
                &ObligationCause::dummy(),
                param_env,
                Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
            );
            // FIXME(compiler-errors): We may benefit from resolving regions here.
            if ocx.try_evaluate_obligations().is_empty()
                && let item_ty = infcx.resolve_vars_if_possible(item_ty)
                && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
                && let Some(sugg) = formatter(
                    infcx.tcx,
                    infcx.resolve_vars_if_possible(args),
                    trait_def_id,
                    assoc_item_def_id,
                    item_ty,
                )
            {
                return Some(sugg);
            }

            None
        });

        if sugg.is_some() {
            return sugg;
        }
    }
    None
}

fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
    let icx = ItemCtxt::new(tcx, def_id);
    let item = tcx.hir_expect_item(def_id);
    let impl_ = item.expect_impl();
    let of_trait = impl_
        .of_trait
        .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}"));
    let selfty = tcx.type_of(def_id).instantiate_identity();
    let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);

    check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref);

    let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);

    ty::ImplTraitHeader {
        trait_ref: ty::EarlyBinder::bind(trait_ref),
        safety: of_trait.safety,
        polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
        constness: impl_.constness,
    }
}

fn check_impl_constness(
    tcx: TyCtxt<'_>,
    constness: hir::Constness,
    hir_trait_ref: &hir::TraitRef<'_>,
) {
    if let hir::Constness::NotConst = constness {
        return;
    }

    let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
    if tcx.is_const_trait(trait_def_id) {
        return;
    }

    let trait_name = tcx.item_name(trait_def_id).to_string();
    let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build())
    {
        (Some(trait_def_id), true) => {
            let span = tcx.hir_expect_item(trait_def_id).vis_span;
            let span = tcx.sess.source_map().span_extend_while_whitespace(span);

            (
                Some(span.shrink_to_hi()),
                if tcx.features().const_trait_impl() {
                    ""
                } else {
                    "enable `#![feature(const_trait_impl)]` in your crate and "
                },
            )
        }
        (None, _) | (_, false) => (None, ""),
    };
    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
        trait_ref_span: hir_trait_ref.path.span,
        trait_name,
        suggestion,
        suggestion_pre,
        marking: (),
        adding: (),
    });
}

fn polarity_of_impl(
    tcx: TyCtxt<'_>,
    of_trait: &hir::TraitImplHeader<'_>,
    is_rustc_reservation: bool,
) -> ty::ImplPolarity {
    match of_trait.polarity {
        hir::ImplPolarity::Negative(span) => {
            if is_rustc_reservation {
                let span = span.to(of_trait.trait_ref.path.span);
                tcx.dcx().span_err(span, "reservation impls can't be negative");
            }
            ty::ImplPolarity::Negative
        }
        hir::ImplPolarity::Positive => {
            if is_rustc_reservation {
                ty::ImplPolarity::Reservation
            } else {
                ty::ImplPolarity::Positive
            }
        }
    }
}

/// Returns the early-bound lifetimes declared in this generics
/// listing. For anything other than fns/methods, this is just all
/// the lifetimes that are declared. For fns or methods, we have to
/// screen out those that do not appear in any where-clauses etc using
/// `resolve_lifetime::early_bound_lifetimes`.
fn early_bound_lifetimes_from_generics<'a, 'tcx>(
    tcx: TyCtxt<'tcx>,
    generics: &'a hir::Generics<'a>,
) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
    generics.params.iter().filter(move |param| match param.kind {
        GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
        _ => false,
    })
}

fn compute_sig_of_foreign_fn_decl<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: LocalDefId,
    decl: &'tcx hir::FnDecl<'tcx>,
    abi: ExternAbi,
    safety: hir::Safety,
) -> ty::PolyFnSig<'tcx> {
    let hir_id = tcx.local_def_id_to_hir_id(def_id);
    let fty =
        ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);

    // Feature gate SIMD types in FFI, since I am not sure that the
    // ABIs are handled at all correctly. -huonw
    if !tcx.features().simd_ffi() {
        let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
            if ty.is_simd() {
                let snip = tcx
                    .sess
                    .source_map()
                    .span_to_snippet(hir_ty.span)
                    .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
                tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
            }
        };
        for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
            check(input, *ty)
        }
        if let hir::FnRetTy::Return(ty) = decl.output {
            check(ty, fty.output().skip_binder())
        }
    }

    fty
}

fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
    match tcx.hir_node_by_def_id(def_id) {
        Node::Expr(&hir::Expr {
            kind:
                hir::ExprKind::Closure(&rustc_hir::Closure {
                    kind: hir::ClosureKind::Coroutine(kind),
                    ..
                }),
            ..
        }) => Some(kind),
        _ => None,
    }
}

fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
    let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
        tcx.hir_node_by_def_id(def_id).expect_closure()
    else {
        bug!()
    };

    let &hir::Expr {
        kind:
            hir::ExprKind::Closure(&rustc_hir::Closure {
                def_id,
                kind: hir::ClosureKind::Coroutine(_),
                ..
            }),
        ..
    } = tcx.hir_body(body).value
    else {
        bug!()
    };

    def_id.to_def_id()
}

fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
    match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
        hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
            hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
        }
        hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
            hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
        }
        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
            hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
        }
    }
}

fn rendered_precise_capturing_args<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: LocalDefId,
) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
    if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
        tcx.opt_rpitit_info(def_id.to_def_id())
    {
        return tcx.rendered_precise_capturing_args(opaque_def_id);
    }

    tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
        hir::GenericBound::Use(args, ..) => {
            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
                PreciseCapturingArgKind::Lifetime(_) => {
                    PreciseCapturingArgKind::Lifetime(arg.name())
                }
                PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
            })))
        }
        _ => None,
    })
}

fn const_param_default<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
    let default_ct = match tcx.hir_node_by_def_id(def_id) {
        hir::Node::GenericParam(hir::GenericParam {
            kind: hir::GenericParamKind::Const { default: Some(ct), .. },
            ..
        }) => ct,
        _ => span_bug!(
            tcx.def_span(def_id),
            "`const_param_default` expected a generic parameter with a constant"
        ),
    };
    let icx = ItemCtxt::new(tcx, def_id);
    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
    let ct = icx
        .lowerer()
        .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
    ty::EarlyBinder::bind(ct)
}

fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
    let hir_id = tcx.local_def_id_to_hir_id(def);
    let const_arg_id = tcx.parent_hir_id(hir_id);
    match tcx.hir_node(const_arg_id) {
        hir::Node::ConstArg(_) => {
            let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id));
            if tcx.features().generic_const_exprs() {
                ty::AnonConstKind::GCE
            } else if tcx.features().min_generic_const_args() {
                ty::AnonConstKind::MCG
            } else if let hir::Node::Expr(hir::Expr {
                kind: hir::ExprKind::Repeat(_, repeat_count),
                ..
            }) = parent_hir_node
                && repeat_count.hir_id == const_arg_id
            {
                ty::AnonConstKind::RepeatExprCount
            } else {
                ty::AnonConstKind::MCG
            }
        }
        _ => ty::AnonConstKind::NonTypeSystem,
    }
}

#[instrument(level = "debug", skip(tcx), ret)]
fn const_of_item<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
    let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
        hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
        hir::Node::TraitItem(hir::TraitItem {
            kind: hir::TraitItemKind::Const(.., ct), ..
        }) => ct.expect("no default value for trait assoc const"),
        hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
        _ => {
            span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
        }
    };
    let ct_arg = match ct_rhs {
        hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
        hir::ConstItemRhs::Body(_) => {
            let e = tcx.dcx().span_delayed_bug(
                tcx.def_span(def_id),
                "cannot call const_of_item on a non-type_const",
            );
            return ty::EarlyBinder::bind(Const::new_error(tcx, e));
        }
    };
    let icx = ItemCtxt::new(tcx, def_id);
    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
    let ct = icx
        .lowerer()
        .lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
    if let Err(e) = icx.check_tainted_by_errors()
        && !ct.references_error()
    {
        ty::EarlyBinder::bind(Const::new_error(tcx, e))
    } else {
        ty::EarlyBinder::bind(ct)
    }
}
