about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs214
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs331
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs162
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs37
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs1
7 files changed, 354 insertions, 415 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a361679e8ad..f4fcb13b1a1 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -10,7 +10,7 @@ use rustc_errors::{EmissionGuarantee, MultiSpan};
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::{LangItem, Node, intravisit};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
-use rustc_infer::traits::{Obligation, ObligationCauseCode};
+use rustc_infer::traits::{Obligation, ObligationCauseCode, WellFormedLoc};
 use rustc_lint_defs::builtin::{
     REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
 };
@@ -36,6 +36,10 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 use super::compare_impl_item::check_type_bounds;
 use super::*;
+use crate::check::wfcheck::{
+    check_associated_item, check_trait_item, check_variances_for_type_defn, check_where_clauses,
+    enter_wf_checking_ctxt,
+};
 
 fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
     if let ExternAbi::Cdecl { unwind } = abi {
@@ -729,7 +733,8 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     }
 }
 
-pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
+    let mut res = Ok(());
     let generics = tcx.generics_of(def_id);
 
     for param in &generics.own_params {
@@ -754,15 +759,39 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     }
 
     match tcx.def_kind(def_id) {
-        DefKind::Static { .. } => {
-            check_static_inhabited(tcx, def_id);
-            check_static_linkage(tcx, def_id);
+        def_kind @ (DefKind::Static { .. } | DefKind::Const) => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            match def_kind {
+                DefKind::Static { .. } => {
+                    check_static_inhabited(tcx, def_id);
+                    check_static_linkage(tcx, def_id);
+                    res = res.and(wfcheck::check_static_item(tcx, def_id));
+
+                    // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+                    // checks. Returning early here does not miss any checks and
+                    // avoids this query from having a direct dependency edge on the HIR
+                    return res;
+                }
+                DefKind::Const => {}
+                _ => unreachable!(),
+            }
         }
-        DefKind::Const => {}
         DefKind::Enum => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id());
             check_enum(tcx, def_id);
+            check_variances_for_type_defn(tcx, def_id);
         }
         DefKind::Fn => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            tcx.ensure_ok().fn_sig(def_id);
+            tcx.ensure_ok().codegen_fn_attrs(def_id);
             if let Some(i) = tcx.intrinsic(def_id) {
                 intrinsic::check_intrinsic_type(
                     tcx,
@@ -773,17 +802,31 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             }
         }
         DefKind::Impl { of_trait } => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().impl_trait_header(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            tcx.ensure_ok().associated_items(def_id);
             if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
-                if tcx
-                    .ensure_ok()
-                    .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
-                    .is_ok()
-                {
+                res = res.and(
+                    tcx.ensure_ok()
+                        .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id),
+                );
+
+                if res.is_ok() {
+                    // Checking this only makes sense if the all trait impls satisfy basic
+                    // requirements (see `coherent_trait` query), otherwise
+                    // we run into infinite recursions a lot.
                     check_impl_items_against_trait(tcx, def_id, impl_trait_header);
                 }
             }
         }
         DefKind::Trait => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().trait_def(def_id);
+            tcx.ensure_ok().explicit_super_predicates_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            tcx.ensure_ok().associated_items(def_id);
             let assoc_items = tcx.associated_items(def_id);
             check_on_unimplemented(tcx, def_id);
 
@@ -802,11 +845,33 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 }
             }
         }
-        DefKind::Struct => {
-            check_struct(tcx, def_id);
+        DefKind::TraitAlias => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().explicit_implied_predicates_of(def_id);
+            tcx.ensure_ok().explicit_super_predicates_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
         }
-        DefKind::Union => {
-            check_union(tcx, def_id);
+        def_kind @ (DefKind::Struct | DefKind::Union) => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+
+            let adt = tcx.adt_def(def_id).non_enum_variant();
+            for f in adt.fields.iter() {
+                tcx.ensure_ok().generics_of(f.did);
+                tcx.ensure_ok().type_of(f.did);
+                tcx.ensure_ok().predicates_of(f.did);
+            }
+
+            if let Some((_, ctor_def_id)) = adt.ctor {
+                crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local());
+            }
+            match def_kind {
+                DefKind::Struct => check_struct(tcx, def_id),
+                DefKind::Union => check_union(tcx, def_id),
+                _ => unreachable!(),
+            }
+            check_variances_for_type_defn(tcx, def_id);
         }
         DefKind::OpaqueTy => {
             check_opaque_precise_captures(tcx, def_id);
@@ -831,14 +896,37 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 tcx.ensure_ok().explicit_implied_const_bounds(def_id);
                 tcx.ensure_ok().const_conditions(def_id);
             }
+
+            // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+            // checks. Returning early here does not miss any checks and
+            // avoids this query from having a direct dependency edge on the HIR
+            return res;
         }
         DefKind::TyAlias => {
+            tcx.ensure_ok().generics_of(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
             check_type_alias_type_params_are_used(tcx, def_id);
+            if tcx.type_alias_is_lazy(def_id) {
+                res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
+                    let ty = tcx.type_of(def_id).instantiate_identity();
+                    let span = tcx.def_span(def_id);
+                    let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
+                    wfcx.register_wf_obligation(
+                        span,
+                        Some(WellFormedLoc::Ty(def_id)),
+                        item_ty.into(),
+                    );
+                    check_where_clauses(wfcx, def_id);
+                    Ok(())
+                }));
+                check_variances_for_type_defn(tcx, def_id);
+            }
         }
         DefKind::ForeignMod => {
             let it = tcx.hir_expect_item(def_id);
             let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
-                return;
+                return Ok(());
             };
 
             check_abi(tcx, it.hir_id(), it.span, abi);
@@ -877,15 +965,23 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 }
 
                 let item = tcx.hir_foreign_item(item.id);
-                match &item.kind {
-                    hir::ForeignItemKind::Fn(sig, _, _) => {
+                tcx.ensure_ok().generics_of(item.owner_id);
+                tcx.ensure_ok().type_of(item.owner_id);
+                tcx.ensure_ok().predicates_of(item.owner_id);
+                if tcx.is_conditionally_const(def_id) {
+                    tcx.ensure_ok().explicit_implied_const_bounds(def_id);
+                    tcx.ensure_ok().const_conditions(def_id);
+                }
+                match item.kind {
+                    hir::ForeignItemKind::Fn(sig, ..) => {
+                        tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
+                        tcx.ensure_ok().fn_sig(item.owner_id);
                         require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
                     }
                     hir::ForeignItemKind::Static(..) => {
-                        check_static_inhabited(tcx, def_id);
-                        check_static_linkage(tcx, def_id);
+                        tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
                     }
-                    _ => {}
+                    _ => (),
                 }
             }
         }
@@ -897,9 +993,85 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             // We do not call `type_of` for closures here as that
             // depends on typecheck and would therefore hide
             // any further errors in case one typeck fails.
+
+            // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+            // checks. Returning early here does not miss any checks and
+            // avoids this query from having a direct dependency edge on the HIR
+            return res;
+        }
+        DefKind::AssocFn => {
+            tcx.ensure_ok().codegen_fn_attrs(def_id);
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().fn_sig(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            res = res.and(check_associated_item(tcx, def_id));
+            let assoc_item = tcx.associated_item(def_id);
+            match assoc_item.container {
+                ty::AssocItemContainer::Impl => {}
+                ty::AssocItemContainer::Trait => {
+                    res = res.and(check_trait_item(tcx, def_id));
+                }
+            }
+
+            // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+            // checks. Returning early here does not miss any checks and
+            // avoids this query from having a direct dependency edge on the HIR
+            return res;
+        }
+        DefKind::AssocConst => {
+            tcx.ensure_ok().type_of(def_id);
+            tcx.ensure_ok().predicates_of(def_id);
+            res = res.and(check_associated_item(tcx, def_id));
+            let assoc_item = tcx.associated_item(def_id);
+            match assoc_item.container {
+                ty::AssocItemContainer::Impl => {}
+                ty::AssocItemContainer::Trait => {
+                    res = res.and(check_trait_item(tcx, def_id));
+                }
+            }
+
+            // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+            // checks. Returning early here does not miss any checks and
+            // avoids this query from having a direct dependency edge on the HIR
+            return res;
         }
+        DefKind::AssocTy => {
+            tcx.ensure_ok().predicates_of(def_id);
+            res = res.and(check_associated_item(tcx, def_id));
+
+            let assoc_item = tcx.associated_item(def_id);
+            let has_type = match assoc_item.container {
+                ty::AssocItemContainer::Impl => true,
+                ty::AssocItemContainer::Trait => {
+                    tcx.ensure_ok().item_bounds(def_id);
+                    tcx.ensure_ok().item_self_bounds(def_id);
+                    res = res.and(check_trait_item(tcx, def_id));
+                    assoc_item.defaultness(tcx).has_value()
+                }
+            };
+            if has_type {
+                tcx.ensure_ok().type_of(def_id);
+            }
+
+            // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+            // checks. Returning early here does not miss any checks and
+            // avoids this query from having a direct dependency edge on the HIR
+            return res;
+        }
+
+        // Only `Node::Item` and `Node::ForeignItem` still have HIR based
+        // checks. Returning early here does not miss any checks and
+        // avoids this query from having a direct dependency edge on the HIR
+        DefKind::AnonConst | DefKind::InlineConst => return res,
         _ => {}
     }
+    let node = tcx.hir_node_by_def_id(def_id);
+    res.and(match node {
+        hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
+        hir::Node::Item(item) => wfcheck::check_item(tcx, item),
+        hir::Node::ForeignItem(item) => wfcheck::check_foreign_item(tcx, item),
+        _ => unreachable!("{node:?}"),
+    })
 }
 
 pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 060fc51b7bd..cebf7d1b532 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -594,8 +594,9 @@ pub(crate) fn check_intrinsic_type(
         | sym::simd_ceil
         | sym::simd_floor
         | sym::simd_round
+        | sym::simd_round_ties_even
         | sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
-        sym::simd_fma | sym::simd_relaxed_fma => {
+        sym::simd_fma | sym::simd_relaxed_fma | sym::simd_funnel_shl | sym::simd_funnel_shr => {
             (1, 0, vec![param(0), param(0), param(0)], param(0))
         }
         sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index b9124ea0e5e..ed8d25e9915 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -25,7 +25,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
-use rustc_span::{DUMMY_SP, Ident, Span, sym};
+use rustc_span::{DUMMY_SP, Span, sym};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt};
 use rustc_trait_selection::traits::misc::{
@@ -46,7 +46,6 @@ use crate::{errors, fluent_generated as fluent};
 
 pub(super) struct WfCheckingCtxt<'a, 'tcx> {
     pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
-    span: Span,
     body_def_id: LocalDefId,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -84,7 +83,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     /// signature types for implied bounds when checking regions.
     // FIXME(-Znext-solver): This should be removed when we compute implied outlives
     // bounds using the unnormalized signature of the function we're checking.
-    fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
+    pub(super) fn deeply_normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -105,7 +104,12 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
         }
     }
 
-    fn register_wf_obligation(&self, span: Span, loc: Option<WellFormedLoc>, term: ty::Term<'tcx>) {
+    pub(super) fn register_wf_obligation(
+        &self,
+        span: Span,
+        loc: Option<WellFormedLoc>,
+        term: ty::Term<'tcx>,
+    ) {
         let cause = traits::ObligationCause::new(
             span,
             self.body_def_id,
@@ -122,7 +126,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
 
 pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     tcx: TyCtxt<'tcx>,
-    span: Span,
     body_def_id: LocalDefId,
     f: F,
 ) -> Result<(), ErrorGuaranteed>
@@ -133,7 +136,7 @@ where
     let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
     let ocx = ObligationCtxt::new_with_diagnostics(infcx);
 
-    let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
+    let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env };
 
     if !tcx.features().trivial_bounds() {
         wfcx.check_false_global_bounds()
@@ -187,23 +190,10 @@ where
 }
 
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
-    let node = tcx.hir_node_by_def_id(def_id);
-    let mut res = match node {
-        hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
-        hir::Node::Item(item) => check_item(tcx, item),
-        hir::Node::TraitItem(item) => check_trait_item(tcx, item),
-        hir::Node::ImplItem(item) => check_impl_item(tcx, item),
-        hir::Node::ForeignItem(item) => check_foreign_item(tcx, item),
-        hir::Node::ConstBlock(_) | hir::Node::Expr(_) | hir::Node::OpaqueTy(_) => {
-            Ok(crate::check::check::check_item_type(tcx, def_id))
-        }
-        _ => unreachable!("{node:?}"),
-    };
+    let mut res = crate::check::check::check_item_type(tcx, def_id);
 
-    if let Some(generics) = node.generics() {
-        for param in generics.params {
-            res = res.and(check_param_wf(tcx, param));
-        }
+    for param in &tcx.generics_of(def_id).own_params {
+        res = res.and(check_param_wf(tcx, param));
     }
 
     res
@@ -223,16 +213,18 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
-fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<(), ErrorGuaranteed> {
+pub(super) fn check_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item: &'tcx hir::Item<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
     let def_id = item.owner_id.def_id;
 
     debug!(
         ?item.owner_id,
         item.name = ? tcx.def_path_str(def_id)
     );
-    crate::collect::lower_item(tcx, item.item_id());
 
-    let res = match item.kind {
+    match item.kind {
         // Right now we check that every default trait implementation
         // has an implementation of itself. Basically, a case like:
         //
@@ -295,57 +287,18 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
             }
             res
         }
-        hir::ItemKind::Fn { ident, sig, .. } => {
-            check_item_fn(tcx, def_id, ident, item.span, sig.decl)
-        }
-        hir::ItemKind::Static(_, _, ty, _) => {
-            check_static_item(tcx, def_id, ty.span, UnsizedHandling::Forbid)
-        }
-        hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span, item.span),
-        hir::ItemKind::Struct(_, generics, _) => {
-            let res = check_type_defn(tcx, item, false);
-            check_variances_for_type_defn(tcx, item, generics);
-            res
-        }
-        hir::ItemKind::Union(_, generics, _) => {
-            let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, generics);
-            res
-        }
-        hir::ItemKind::Enum(_, generics, _) => {
-            let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, generics);
-            res
-        }
+        hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),
+        hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span),
+        hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false),
+        hir::ItemKind::Union(..) => check_type_defn(tcx, item, true),
+        hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true),
         hir::ItemKind::Trait(..) => check_trait(tcx, item),
         hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
-        // `ForeignItem`s are handled separately.
-        hir::ItemKind::ForeignMod { .. } => Ok(()),
-        hir::ItemKind::TyAlias(_, generics, hir_ty) if tcx.type_alias_is_lazy(item.owner_id) => {
-            let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
-                let ty = tcx.type_of(def_id).instantiate_identity();
-                let item_ty =
-                    wfcx.deeply_normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty);
-                wfcx.register_wf_obligation(
-                    hir_ty.span,
-                    Some(WellFormedLoc::Ty(def_id)),
-                    item_ty.into(),
-                );
-                check_where_clauses(wfcx, item.span, def_id);
-                Ok(())
-            });
-            check_variances_for_type_defn(tcx, item, generics);
-            res
-        }
         _ => Ok(()),
-    };
-
-    crate::check::check::check_item_type(tcx, def_id);
-
-    res
+    }
 }
 
-fn check_foreign_item<'tcx>(
+pub(super) fn check_foreign_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::ForeignItem<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
@@ -357,43 +310,23 @@ fn check_foreign_item<'tcx>(
     );
 
     match item.kind {
-        hir::ForeignItemKind::Fn(sig, ..) => {
-            check_item_fn(tcx, def_id, item.ident, item.span, sig.decl)
-        }
-        hir::ForeignItemKind::Static(ty, ..) => {
-            check_static_item(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
-        }
-        hir::ForeignItemKind::Type => Ok(()),
+        hir::ForeignItemKind::Fn(sig, ..) => check_item_fn(tcx, def_id, sig.decl),
+        hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => Ok(()),
     }
 }
 
-fn check_trait_item<'tcx>(
+pub(crate) fn check_trait_item<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_item: &'tcx hir::TraitItem<'tcx>,
+    def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
-    let def_id = trait_item.owner_id.def_id;
-
-    crate::collect::lower_trait_item(tcx, trait_item.trait_item_id());
-
-    let (method_sig, span) = match trait_item.kind {
-        hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
-        hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
-        _ => (None, trait_item.span),
-    };
-
     // Check that an item definition in a subtrait is shadowing a supertrait item.
     lint_item_shadowing_supertrait_item(tcx, def_id);
 
-    let mut res = check_associated_item(tcx, def_id, span, method_sig);
+    let mut res = Ok(());
 
-    if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
+    if matches!(tcx.def_kind(def_id), DefKind::AssocFn) {
         for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
-            res = res.and(check_associated_item(
-                tcx,
-                assoc_ty_def_id.expect_local(),
-                tcx.def_span(assoc_ty_def_id),
-                None,
-            ));
+            res = res.and(check_associated_item(tcx, assoc_ty_def_id.expect_local()));
         }
     }
     res
@@ -872,67 +805,54 @@ fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_i
     }
 }
 
-fn check_impl_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    impl_item: &'tcx hir::ImplItem<'tcx>,
-) -> Result<(), ErrorGuaranteed> {
-    crate::collect::lower_impl_item(tcx, impl_item.impl_item_id());
-
-    let (method_sig, span) = match impl_item.kind {
-        hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
-        // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
-        hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
-        _ => (None, impl_item.span),
-    };
-    check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
-}
-
-fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), ErrorGuaranteed> {
+fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), ErrorGuaranteed> {
     match param.kind {
         // We currently only check wf of const params here.
-        hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
+        ty::GenericParamDefKind::Lifetime | ty::GenericParamDefKind::Type { .. } => Ok(()),
 
         // Const parameters are well formed if their type is structural match.
-        hir::GenericParamKind::Const { ty: hir_ty, default: _, synthetic: _ } => {
+        ty::GenericParamDefKind::Const { .. } => {
             let ty = tcx.type_of(param.def_id).instantiate_identity();
+            let span = tcx.def_span(param.def_id);
+            let def_id = param.def_id.expect_local();
 
             if tcx.features().unsized_const_params() {
-                enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
+                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
                     wfcx.register_bound(
-                        ObligationCause::new(
-                            hir_ty.span,
-                            param.def_id,
-                            ObligationCauseCode::ConstParam(ty),
-                        ),
+                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
                         wfcx.param_env,
                         ty,
-                        tcx.require_lang_item(LangItem::UnsizedConstParamTy, hir_ty.span),
+                        tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
                     );
                     Ok(())
                 })
             } else if tcx.features().adt_const_params() {
-                enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
+                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
                     wfcx.register_bound(
-                        ObligationCause::new(
-                            hir_ty.span,
-                            param.def_id,
-                            ObligationCauseCode::ConstParam(ty),
-                        ),
+                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
                         wfcx.param_env,
                         ty,
-                        tcx.require_lang_item(LangItem::ConstParamTy, hir_ty.span),
+                        tcx.require_lang_item(LangItem::ConstParamTy, span),
                     );
                     Ok(())
                 })
             } else {
+                let span = || {
+                    let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
+                        tcx.hir_node_by_def_id(def_id).expect_generic_param().kind
+                    else {
+                        bug!()
+                    };
+                    span
+                };
                 let mut diag = match ty.kind() {
                     ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
                     ty::FnPtr(..) => tcx.dcx().struct_span_err(
-                        hir_ty.span,
+                        span(),
                         "using function pointers as const generic parameters is forbidden",
                     ),
                     ty::RawPtr(_, _) => tcx.dcx().struct_span_err(
-                        hir_ty.span,
+                        span(),
                         "using raw pointers as const generic parameters is forbidden",
                     ),
                     _ => {
@@ -940,7 +860,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                         ty.error_reported()?;
 
                         tcx.dcx().struct_span_err(
-                            hir_ty.span,
+                            span(),
                             format!(
                                 "`{ty}` is forbidden as the type of a const generic parameter",
                             ),
@@ -950,7 +870,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
 
                 diag.note("the only supported types are integers, `bool`, and `char`");
 
-                let cause = ObligationCause::misc(hir_ty.span, param.def_id);
+                let cause = ObligationCause::misc(span(), def_id);
                 let adt_const_params_feature_string =
                     " more complex and user defined types".to_string();
                 let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
@@ -1010,15 +930,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
     }
 }
 
-#[instrument(level = "debug", skip(tcx, span, sig_if_method))]
-fn check_associated_item(
+#[instrument(level = "debug", skip(tcx))]
+pub(crate) fn check_associated_item(
     tcx: TyCtxt<'_>,
     item_id: LocalDefId,
-    span: Span,
-    sig_if_method: Option<&hir::FnSig<'_>>,
 ) -> Result<(), ErrorGuaranteed> {
     let loc = Some(WellFormedLoc::Ty(item_id));
-    enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
         let item = tcx.associated_item(item_id);
 
         // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
@@ -1033,6 +951,8 @@ fn check_associated_item(
             }
         };
 
+        let span = tcx.def_span(item_id);
+
         match item.kind {
             ty::AssocKind::Const { .. } => {
                 let ty = tcx.type_of(item.def_id).instantiate_identity();
@@ -1049,14 +969,9 @@ fn check_associated_item(
             }
             ty::AssocKind::Fn { .. } => {
                 let sig = tcx.fn_sig(item.def_id).instantiate_identity();
-                let hir_sig = sig_if_method.expect("bad signature for method");
-                check_fn_or_method(
-                    wfcx,
-                    item.ident(tcx).span,
-                    sig,
-                    hir_sig.decl,
-                    item.def_id.expect_local(),
-                );
+                let hir_sig =
+                    tcx.hir_node_by_def_id(item_id).fn_sig().expect("bad signature for method");
+                check_fn_or_method(wfcx, sig, hir_sig.decl, item_id);
                 check_method_receiver(wfcx, hir_sig, item, self_ty)
             }
             ty::AssocKind::Type { .. } => {
@@ -1083,7 +998,7 @@ fn check_type_defn<'tcx>(
     let _ = tcx.representability(item.owner_id.def_id);
     let adt_def = tcx.adt_def(item.owner_id);
 
-    enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
         let variants = adt_def.variants();
         let packed = adt_def.repr().packed();
 
@@ -1185,7 +1100,7 @@ fn check_type_defn<'tcx>(
             }
         }
 
-        check_where_clauses(wfcx, item.span, item.owner_id.def_id);
+        check_where_clauses(wfcx, item.owner_id.def_id);
         Ok(())
     })
 }
@@ -1215,8 +1130,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
         }
     }
 
-    let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
-        check_where_clauses(wfcx, item.span, def_id);
+    let res = enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
+        check_where_clauses(wfcx, def_id);
         Ok(())
     });
 
@@ -1252,72 +1167,63 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
 fn check_item_fn(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-    ident: Ident,
-    span: Span,
     decl: &hir::FnDecl<'_>,
 ) -> Result<(), ErrorGuaranteed> {
-    enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
         let sig = tcx.fn_sig(def_id).instantiate_identity();
-        check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
+        check_fn_or_method(wfcx, sig, decl, def_id);
         Ok(())
     })
 }
 
-enum UnsizedHandling {
-    Forbid,
-    AllowIfForeignTail,
-}
-
-#[instrument(level = "debug", skip(tcx, ty_span, unsized_handling))]
-fn check_static_item(
+#[instrument(level = "debug", skip(tcx))]
+pub(super) fn check_static_item(
     tcx: TyCtxt<'_>,
     item_id: LocalDefId,
-    ty_span: Span,
-    unsized_handling: UnsizedHandling,
 ) -> Result<(), ErrorGuaranteed> {
-    enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
         let ty = tcx.type_of(item_id).instantiate_identity();
-        let item_ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
-
-        let forbid_unsized = match unsized_handling {
-            UnsizedHandling::Forbid => true,
-            UnsizedHandling::AllowIfForeignTail => {
-                let tail =
-                    tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
-                !matches!(tail.kind(), ty::Foreign(_))
-            }
+        let item_ty = wfcx.deeply_normalize(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), ty);
+
+        let is_foreign_item = tcx.is_foreign_item(item_id);
+
+        let forbid_unsized = !is_foreign_item || {
+            let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.infcx.typing_env(wfcx.param_env));
+            !matches!(tail.kind(), ty::Foreign(_))
         };
 
-        wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
+        wfcx.register_wf_obligation(DUMMY_SP, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
         if forbid_unsized {
+            let span = tcx.def_span(item_id);
             wfcx.register_bound(
                 traits::ObligationCause::new(
-                    ty_span,
+                    span,
                     wfcx.body_def_id,
                     ObligationCauseCode::SizedConstOrStatic,
                 ),
                 wfcx.param_env,
                 item_ty,
-                tcx.require_lang_item(LangItem::Sized, ty_span),
+                tcx.require_lang_item(LangItem::Sized, span),
             );
         }
 
         // Ensure that the end result is `Sync` in a non-thread local `static`.
         let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
             == Some(hir::Mutability::Not)
-            && !tcx.is_foreign_item(item_id.to_def_id())
+            && !is_foreign_item
             && !tcx.is_thread_local_static(item_id.to_def_id());
 
         if should_check_for_sync {
+            let span = tcx.def_span(item_id);
             wfcx.register_bound(
                 traits::ObligationCause::new(
-                    ty_span,
+                    span,
                     wfcx.body_def_id,
                     ObligationCauseCode::SharedStatic,
                 ),
                 wfcx.param_env,
                 item_ty,
-                tcx.require_lang_item(LangItem::Sync, ty_span),
+                tcx.require_lang_item(LangItem::Sync, span),
             );
         }
         Ok(())
@@ -1328,9 +1234,8 @@ fn check_const_item(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
     ty_span: Span,
-    item_span: Span,
 ) -> Result<(), ErrorGuaranteed> {
-    enter_wf_checking_ctxt(tcx, ty_span, def_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
         let ty = tcx.type_of(def_id).instantiate_identity();
         let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
 
@@ -1346,7 +1251,7 @@ fn check_const_item(
             tcx.require_lang_item(LangItem::Sized, ty_span),
         );
 
-        check_where_clauses(wfcx, item_span, def_id);
+        check_where_clauses(wfcx, def_id);
 
         Ok(())
     })
@@ -1359,7 +1264,7 @@ fn check_impl<'tcx>(
     hir_self_ty: &hir::Ty<'_>,
     hir_trait_ref: &Option<hir::TraitRef<'_>>,
 ) -> Result<(), ErrorGuaranteed> {
-    enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
+    enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
         match hir_trait_ref {
             Some(hir_trait_ref) => {
                 // `#[rustc_reservation_impl]` impls are not real impls and
@@ -1443,14 +1348,14 @@ fn check_impl<'tcx>(
             }
         }
 
-        check_where_clauses(wfcx, item.span, item.owner_id.def_id);
+        check_where_clauses(wfcx, item.owner_id.def_id);
         Ok(())
     })
 }
 
 /// Checks where-clauses and inline bounds that are declared on `def_id`.
 #[instrument(level = "debug", skip(wfcx))]
-fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id: LocalDefId) {
+pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId) {
     let infcx = wfcx.infcx;
     let tcx = wfcx.tcx();
 
@@ -1605,21 +1510,18 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
 
     let predicates = predicates.instantiate_identity(tcx);
 
-    let predicates = wfcx.normalize(span, None, predicates);
-
-    debug!(?predicates.predicates);
     assert_eq!(predicates.predicates.len(), predicates.spans.len());
     let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
+        let p = wfcx.normalize(sp, None, p);
         traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
     });
     let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
     wfcx.register_obligations(obligations);
 }
 
-#[instrument(level = "debug", skip(wfcx, span, hir_decl))]
+#[instrument(level = "debug", skip(wfcx, hir_decl))]
 fn check_fn_or_method<'tcx>(
     wfcx: &WfCheckingCtxt<'_, 'tcx>,
-    span: Span,
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
     def_id: LocalDefId,
@@ -1657,7 +1559,7 @@ fn check_fn_or_method<'tcx>(
         );
     }
 
-    check_where_clauses(wfcx, span, def_id);
+    check_where_clauses(wfcx, def_id);
 
     if sig.abi == ExternAbi::RustCall {
         let span = tcx.def_span(def_id);
@@ -1746,17 +1648,18 @@ fn check_method_receiver<'tcx>(
     }
 
     let span = fn_sig.decl.inputs[0].span;
+    let loc = Some(WellFormedLoc::Param { function: method.def_id.expect_local(), param_idx: 0 });
 
     let sig = tcx.fn_sig(method.def_id).instantiate_identity();
     let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
-    let sig = wfcx.normalize(span, None, sig);
+    let sig = wfcx.normalize(DUMMY_SP, loc, sig);
 
     debug!("check_method_receiver: sig={:?}", sig);
 
-    let self_ty = wfcx.normalize(span, None, self_ty);
+    let self_ty = wfcx.normalize(DUMMY_SP, loc, self_ty);
 
     let receiver_ty = sig.inputs()[0];
-    let receiver_ty = wfcx.normalize(span, None, receiver_ty);
+    let receiver_ty = wfcx.normalize(DUMMY_SP, loc, receiver_ty);
 
     // If the receiver already has errors reported, consider it valid to avoid
     // unnecessary errors (#58712).
@@ -2004,27 +1907,23 @@ fn legacy_receiver_is_implemented<'tcx>(
     }
 }
 
-fn check_variances_for_type_defn<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    item: &'tcx hir::Item<'tcx>,
-    hir_generics: &hir::Generics<'tcx>,
-) {
-    match item.kind {
-        ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
+pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
+    match tcx.def_kind(def_id) {
+        DefKind::Enum | DefKind::Struct | DefKind::Union => {
             // Ok
         }
-        ItemKind::TyAlias(..) => {
+        DefKind::TyAlias => {
             assert!(
-                tcx.type_alias_is_lazy(item.owner_id),
+                tcx.type_alias_is_lazy(def_id),
                 "should not be computing variance of non-free type alias"
             );
         }
-        kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"),
+        kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"),
     }
 
-    let ty_predicates = tcx.predicates_of(item.owner_id);
+    let ty_predicates = tcx.predicates_of(def_id);
     assert_eq!(ty_predicates.parent, None);
-    let variances = tcx.variances_of(item.owner_id);
+    let variances = tcx.variances_of(def_id);
 
     let mut constrained_parameters: FxHashSet<_> = variances
         .iter()
@@ -2037,8 +1936,10 @@ fn check_variances_for_type_defn<'tcx>(
 
     // Lazily calculated because it is only needed in case of an error.
     let explicitly_bounded_params = LazyCell::new(|| {
-        let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id);
-        hir_generics
+        let icx = crate::collect::ItemCtxt::new(tcx, def_id);
+        tcx.hir_node_by_def_id(def_id)
+            .generics()
+            .unwrap()
             .predicates
             .iter()
             .filter_map(|predicate| match predicate.kind {
@@ -2053,8 +1954,6 @@ fn check_variances_for_type_defn<'tcx>(
             .collect::<FxHashSet<_>>()
     });
 
-    let ty_generics = tcx.generics_of(item.owner_id);
-
     for (index, _) in variances.iter().enumerate() {
         let parameter = Parameter(index as u32);
 
@@ -2062,9 +1961,13 @@ fn check_variances_for_type_defn<'tcx>(
             continue;
         }
 
-        let ty_param = &ty_generics.own_params[index];
+        let node = tcx.hir_node_by_def_id(def_id);
+        let item = node.expect_item();
+        let hir_generics = node.generics().unwrap();
         let hir_param = &hir_generics.params[index];
 
+        let ty_param = &tcx.generics_of(item.owner_id).own_params[index];
+
         if ty_param.def_id != hir_param.def_id.into() {
             // Valid programs always have lifetimes before types in the generic parameter list.
             // ty_generics are normalized to be in this required order, and variances are built
@@ -2082,7 +1985,7 @@ fn check_variances_for_type_defn<'tcx>(
 
         // Look for `ErrorGuaranteed` deeply within this type.
         if let ControlFlow::Break(ErrorGuaranteed { .. }) = tcx
-            .type_of(item.owner_id)
+            .type_of(def_id)
             .instantiate_identity()
             .visit_with(&mut HasErrorDeep { tcx, seen: Default::default() })
         {
@@ -2301,7 +2204,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn check_false_global_bounds(&mut self) {
         let tcx = self.ocx.infcx.tcx;
-        let mut span = self.span;
+        let mut span = tcx.def_span(self.body_def_id);
         let empty_env = ty::ParamEnv::empty();
 
         let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index d7568554669..b10d5b55789 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -277,17 +277,7 @@ impl<'tcx> ItemCtxt<'tcx> {
             }
             _ => self.item_def_id,
         };
-        // FIXME: just invoke `tcx.def_descr` instead of going through the HIR
-        // Can also remove most `descr` methods then.
-        let kind = match self.tcx.hir_node_by_def_id(kind_id) {
-            Node::Item(it) => it.kind.descr(),
-            Node::ImplItem(it) => it.kind.descr(),
-            Node::TraitItem(it) => it.kind.descr(),
-            Node::ForeignItem(it) => it.kind.descr(),
-            Node::OpaqueTy(_) => "opaque type",
-            Node::Synthetic => self.tcx.def_descr(kind_id.into()),
-            node => todo!("{node:#?}"),
-        };
+        let kind = self.tcx.def_descr(kind_id.into());
         let mut diag = placeholder_type_error_diag(
             self,
             generics,
@@ -615,159 +605,13 @@ fn get_new_lifetime_name<'tcx>(
     (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
 }
 
-#[instrument(level = "debug", skip_all)]
-pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
-    let it = tcx.hir_item(item_id);
-    debug!(item = ?it.kind.ident(), id = %it.hir_id());
-    let def_id = item_id.owner_id.def_id;
-
-    match &it.kind {
-        // These don't define types.
-        hir::ItemKind::ExternCrate(..)
-        | hir::ItemKind::Use(..)
-        | hir::ItemKind::Macro(..)
-        | hir::ItemKind::Mod(..)
-        | hir::ItemKind::GlobalAsm { .. } => {}
-        hir::ItemKind::ForeignMod { items, .. } => {
-            for item in *items {
-                let item = tcx.hir_foreign_item(item.id);
-                tcx.ensure_ok().generics_of(item.owner_id);
-                tcx.ensure_ok().type_of(item.owner_id);
-                tcx.ensure_ok().predicates_of(item.owner_id);
-                if tcx.is_conditionally_const(def_id) {
-                    tcx.ensure_ok().explicit_implied_const_bounds(def_id);
-                    tcx.ensure_ok().const_conditions(def_id);
-                }
-                match item.kind {
-                    hir::ForeignItemKind::Fn(..) => {
-                        tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
-                        tcx.ensure_ok().fn_sig(item.owner_id)
-                    }
-                    hir::ForeignItemKind::Static(..) => {
-                        tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
-                    }
-                    _ => (),
-                }
-            }
-        }
-        hir::ItemKind::Enum(..) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-            lower_enum_variant_types(tcx, def_id.to_def_id());
-        }
-        hir::ItemKind::Impl { .. } => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().impl_trait_header(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-            tcx.ensure_ok().associated_items(def_id);
-        }
-        hir::ItemKind::Trait(..) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().trait_def(def_id);
-            tcx.at(it.span).explicit_super_predicates_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-            tcx.ensure_ok().associated_items(def_id);
-        }
-        hir::ItemKind::TraitAlias(..) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.at(it.span).explicit_implied_predicates_of(def_id);
-            tcx.at(it.span).explicit_super_predicates_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-        }
-        hir::ItemKind::Struct(_, _, struct_def) | hir::ItemKind::Union(_, _, struct_def) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-
-            for f in struct_def.fields() {
-                tcx.ensure_ok().generics_of(f.def_id);
-                tcx.ensure_ok().type_of(f.def_id);
-                tcx.ensure_ok().predicates_of(f.def_id);
-            }
-
-            if let Some(ctor_def_id) = struct_def.ctor_def_id() {
-                lower_variant_ctor(tcx, ctor_def_id);
-            }
-        }
-
-        hir::ItemKind::TyAlias(..) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-        }
-
-        hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-        }
-
-        hir::ItemKind::Fn { .. } => {
-            tcx.ensure_ok().generics_of(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().predicates_of(def_id);
-            tcx.ensure_ok().fn_sig(def_id);
-            tcx.ensure_ok().codegen_fn_attrs(def_id);
-        }
-    }
-}
-
-pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
-    let trait_item = tcx.hir_trait_item(trait_item_id);
-    let def_id = trait_item_id.owner_id;
-    tcx.ensure_ok().generics_of(def_id);
-
-    match trait_item.kind {
-        hir::TraitItemKind::Fn(..) => {
-            tcx.ensure_ok().codegen_fn_attrs(def_id);
-            tcx.ensure_ok().type_of(def_id);
-            tcx.ensure_ok().fn_sig(def_id);
-        }
-
-        hir::TraitItemKind::Const(..) => {
-            tcx.ensure_ok().type_of(def_id);
-        }
-
-        hir::TraitItemKind::Type(_, Some(_)) => {
-            tcx.ensure_ok().item_bounds(def_id);
-            tcx.ensure_ok().item_self_bounds(def_id);
-            tcx.ensure_ok().type_of(def_id);
-        }
-
-        hir::TraitItemKind::Type(_, None) => {
-            tcx.ensure_ok().item_bounds(def_id);
-            tcx.ensure_ok().item_self_bounds(def_id);
-        }
-    };
-
-    tcx.ensure_ok().predicates_of(def_id);
-}
-
-pub(super) fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
-    let def_id = impl_item_id.owner_id;
-    tcx.ensure_ok().generics_of(def_id);
-    tcx.ensure_ok().type_of(def_id);
-    tcx.ensure_ok().predicates_of(def_id);
-    let impl_item = tcx.hir_impl_item(impl_item_id);
-    match impl_item.kind {
-        hir::ImplItemKind::Fn(..) => {
-            tcx.ensure_ok().codegen_fn_attrs(def_id);
-            tcx.ensure_ok().fn_sig(def_id);
-        }
-        hir::ImplItemKind::Type(_) => {}
-        hir::ImplItemKind::Const(..) => {}
-    }
-}
-
-fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+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);
 }
 
-fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
+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);
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 7eb896f0bf1..573af01a62d 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,12 +1,11 @@
 use std::assert_matches::assert_matches;
 use std::ops::ControlFlow;
 
-use hir::intravisit::{self, Visitor};
-use hir::{GenericParamKind, HirId, Node};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::VisitorExt;
-use rustc_hir::{self as hir, AmbigArg};
+use rustc_hir::intravisit::{self, Visitor, VisitorExt};
+use rustc_hir::{self as hir, AmbigArg, GenericParamKind, HirId, Node};
+use rustc_middle::span_bug;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_span::{Span, Symbol, kw};
@@ -212,7 +211,19 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
             // inherit the generics of the item.
             Some(parent.to_def_id())
         }
-        _ => None,
+
+        // All of these nodes have no parent from which to inherit generics.
+        Node::Item(_) | Node::ForeignItem(_) => None,
+
+        // Params don't really have generics, but we use it when instantiating their value paths.
+        Node::GenericParam(_) => None,
+
+        Node::Synthetic => span_bug!(
+            tcx.def_span(def_id),
+            "synthetic HIR should have its `generics_of` explicitly fed"
+        ),
+
+        _ => span_bug!(tcx.def_span(def_id), "unhandled node {node:?}"),
     };
 
     enum Defaults {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 74739355e1f..e13daabeb50 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1088,7 +1088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             // FIXME(#97583): Print associated item bindings properly (i.e., not as equality
             // predicates!).
-            // FIXME: Turn this into a structured, translateable & more actionable suggestion.
+            // FIXME: Turn this into a structured, translatable & more actionable suggestion.
             let mut where_bounds = vec![];
             for bound in [bound, bound2].into_iter().chain(matching_candidates) {
                 let bound_id = bound.def_id();
@@ -1588,7 +1588,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             &infcx_
         };
 
-        tcx.all_traits()
+        tcx.all_traits_including_private()
             .filter(|trait_def_id| {
                 // Consider only traits with the associated type
                 tcx.associated_items(*trait_def_id)
@@ -2364,9 +2364,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         };
 
         let lit_input = match expr.kind {
-            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: false }),
             hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
-                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
+                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: true }),
                 _ => None,
             },
             _ => None,
@@ -2433,7 +2433,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 } else {
                     let repr = match repr {
                         TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
-                        TraitObjectSyntax::DynStar => ty::DynStar,
                     };
                     self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
                 }
@@ -2460,13 +2459,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 // type a projection.
                 let in_trait = match opaque_ty.origin {
                     hir::OpaqueTyOrigin::FnReturn {
+                        parent,
                         in_trait_or_impl: Some(hir::RpitContext::Trait),
                         ..
                     }
                     | hir::OpaqueTyOrigin::AsyncFn {
+                        parent,
                         in_trait_or_impl: Some(hir::RpitContext::Trait),
                         ..
-                    } => true,
+                    } => Some(parent),
                     hir::OpaqueTyOrigin::FnReturn {
                         in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                         ..
@@ -2475,7 +2476,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
                         ..
                     }
-                    | hir::OpaqueTyOrigin::TyAlias { .. } => false,
+                    | hir::OpaqueTyOrigin::TyAlias { .. } => None,
                 };
 
                 self.lower_opaque_ty(opaque_ty.def_id, in_trait)
@@ -2595,17 +2596,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
     /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
     #[instrument(level = "debug", skip(self), ret)]
-    fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {
+    fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: Option<LocalDefId>) -> Ty<'tcx> {
         let tcx = self.tcx();
 
         let lifetimes = tcx.opaque_captured_lifetimes(def_id);
         debug!(?lifetimes);
 
-        // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
-        // generate the def_id of an associated type for the trait and return as
-        // type a projection.
-        let def_id = if in_trait {
-            tcx.associated_type_for_impl_trait_in_trait(def_id).to_def_id()
+        // If this is an RPITIT and we are using the new RPITIT lowering scheme,
+        // do a linear search to map this to the synthetic associated type that
+        // it will be lowered to.
+        let def_id = if let Some(parent_def_id) = in_trait {
+            *tcx.associated_types_for_impl_traits_in_associated_fn(parent_def_id)
+                .iter()
+                .find(|rpitit| match tcx.opt_rpitit_info(**rpitit) {
+                    Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+                        opaque_def_id.expect_local() == def_id
+                    }
+                    _ => unreachable!(),
+                })
+                .unwrap()
         } else {
             def_id.to_def_id()
         };
@@ -2628,7 +2637,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         });
         debug!(?args);
 
-        if in_trait {
+        if in_trait.is_some() {
             Ty::new_projection_from_args(tcx, def_id, args)
         } else {
             Ty::new_opaque(tcx, def_id, args)
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 76ab2e57a1b..2ff7caef732 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -65,7 +65,6 @@ This API is completely unstable and subject to change.
 #![feature(debug_closure_helpers)]
 #![feature(gen_blocks)]
 #![feature(if_let_guard)]
-#![feature(iter_from_coroutine)]
 #![feature(iter_intersperse)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]