//! "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;
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,
        ..*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(char::from(c)).take(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: DefId) {
    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<'_>>;

    // 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));
        prev_discr = Some(
            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),
        );

        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(..) => (hir::Constness::NotConst, 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);
    // Only regular traits can be const.
    // FIXME(const_trait_impl): remove this
    let constness = if constness == hir::Constness::Const
        || !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_))
    {
        hir::Constness::Const
    } else {
        hir::Constness::NotConst
    };

    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(
            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(
            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().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.select_where_possible().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) -> Option<ty::ImplTraitHeader<'_>> {
    let icx = ItemCtxt::new(tcx, def_id);
    let item = tcx.hir_expect_item(def_id);
    let impl_ = item.expect_impl();
    let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
    if is_rustc_reservation && impl_.of_trait.is_none() {
        tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
    }
    impl_.of_trait.map(|of_trait| {
        let selfty = tcx.type_of(def_id).instantiate_identity();

        check_impl_constness(tcx, of_trait.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: of_trait.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 (local_trait_span, suggestion_pre) =
        match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
            (true, true) => (
                Some(tcx.def_span(trait_def_id).shrink_to_lo()),
                if tcx.features().const_trait_impl() {
                    ""
                } else {
                    "enable `#![feature(const_trait_impl)]` in your crate and "
                },
            ),
            (false, _) | (_, false) => (None, ""),
        };
    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
        trait_ref_span: hir_trait_ref.path.span,
        trait_name,
        local_trait_span,
        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(_) => {
            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),
                ..
            }) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
                && repeat_count.hir_id == const_arg_id
            {
                ty::AnonConstKind::RepeatExprCount
            } else {
                ty::AnonConstKind::MCG
            }
        }
        _ => ty::AnonConstKind::NonTypeSystem,
    }
}
