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.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs57
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs129
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs62
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs67
-rw-r--r--compiler/rustc_hir_analysis/src/variance/dump.rs13
12 files changed, 200 insertions, 252 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 785258d011c..eb62ff86c71 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -252,10 +252,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
 fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let item = tcx.hir().expect_item(def_id);
-    let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
-        tcx.dcx().span_bug(item.span, "expected opaque item");
-    };
+    let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id);
 
     // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
     // `async-std` (and `pub async fn` in general).
@@ -265,16 +262,16 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         return;
     }
 
-    let span = tcx.def_span(item.owner_id.def_id);
+    let span = tcx.def_span(def_id);
 
-    if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
+    if tcx.type_of(def_id).instantiate_identity().references_error() {
         return;
     }
-    if check_opaque_for_cycles(tcx, item.owner_id.def_id, span).is_err() {
+    if check_opaque_for_cycles(tcx, def_id, span).is_err() {
         return;
     }
 
-    let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, origin);
+    let _ = check_opaque_meets_bounds(tcx, def_id, span, origin);
 }
 
 /// Checks that an opaque type does not contain cycles.
@@ -481,8 +478,7 @@ fn sanity_check_found_hidden_type<'tcx>(
 /// 2. Checking that all lifetimes that are implicitly captured are mentioned.
 /// 3. Asserting that all parameters mentioned in the captures list are invariant.
 fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
-    let hir::OpaqueTy { bounds, .. } =
-        *tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
+    let hir::OpaqueTy { bounds, .. } = *tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
     let Some(precise_capturing_args) = bounds.iter().find_map(|bound| match *bound {
         hir::GenericBound::Use(bounds, ..) => Some(bounds),
         _ => None,
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 35c2b7e7ce2..80334c6efe7 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -93,7 +93,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
         // it's a refinement to a TAIT.
         if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| {
             matches!(
-                node.expect_item().expect_opaque_ty().origin,
+                node.expect_opaque_ty().origin,
                 hir::OpaqueTyOrigin::AsyncFn { parent, .. }  | hir::OpaqueTyOrigin::FnReturn { parent, .. }
                     if parent == impl_m.def_id.expect_local()
             )
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 02d23b95d46..3a9d2640eee 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -185,15 +185,16 @@ where
     }
 }
 
-fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> {
-    let node = tcx.hir_owner_node(def_id);
+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::OwnerNode::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
-        hir::OwnerNode::Item(item) => check_item(tcx, item),
-        hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
-        hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
-        hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
-        hir::OwnerNode::Synthetic => unreachable!(),
+        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::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)),
+        _ => unreachable!(),
     };
 
     if let Some(generics) = node.generics() {
@@ -201,6 +202,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorG
             res = res.and(check_param_wf(tcx, param));
         }
     }
+
     res
 }
 
@@ -2172,10 +2174,14 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
 
 fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
     let items = tcx.hir_module_items(module);
-    let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
-    res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
-    res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
-    res = res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
+    let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id));
+    res =
+        res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
+    res =
+        res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
+    res = res
+        .and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)));
+    res = res.and(items.par_opaques(|item| tcx.ensure().check_well_formed(item)));
     if module == LocalModDefId::CRATE_DEF_ID {
         super::entry::check_for_entry_fn(tcx);
     }
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 93b021be245..640907c3e4a 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -260,8 +260,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
         | hir::ItemKind::Trait(_, _, generics, ..)
         | hir::ItemKind::Impl(hir::Impl { generics, .. })
         | hir::ItemKind::Struct(_, generics) => (generics, true),
-        hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
-        | hir::ItemKind::TyAlias(_, generics) => (generics, false),
+        hir::ItemKind::TyAlias(_, generics) => (generics, false),
         // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type.
         _ => return,
     };
@@ -328,6 +327,19 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
         intravisit::walk_expr(self, expr);
     }
 
+    /// Don't call `type_of` on opaque types, since that depends on type checking function bodies.
+    /// `check_item_type` ensures that it's called instead.
+    fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
+        let def_id = opaque.def_id;
+        self.tcx.ensure().generics_of(def_id);
+        self.tcx.ensure().predicates_of(def_id);
+        self.tcx.ensure().explicit_item_bounds(def_id);
+        self.tcx.ensure().explicit_item_super_predicates(def_id);
+        self.tcx.ensure().item_bounds(def_id);
+        self.tcx.ensure().item_super_predicates(def_id);
+        intravisit::walk_opaque_ty(self, opaque);
+    }
+
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         lower_trait_item(self.tcx, trait_item.trait_item_id());
         intravisit::walk_trait_item(self, trait_item);
@@ -731,18 +743,6 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             }
         }
 
-        // Don't call `type_of` on opaque types, since that depends on type
-        // checking function bodies. `check_item_type` ensures that it's called
-        // instead.
-        hir::ItemKind::OpaqueTy(..) => {
-            tcx.ensure().generics_of(def_id);
-            tcx.ensure().predicates_of(def_id);
-            tcx.ensure().explicit_item_bounds(def_id);
-            tcx.ensure().explicit_item_super_predicates(def_id);
-            tcx.ensure().item_bounds(def_id);
-            tcx.ensure().item_super_predicates(def_id);
-        }
-
         hir::ItemKind::TyAlias(..) => {
             tcx.ensure().generics_of(def_id);
             tcx.ensure().type_of(def_id);
@@ -1852,12 +1852,8 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
 }
 
 fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
-    match tcx.hir_node_by_def_id(def_id) {
-        Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
-            matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
-        }
-        _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
-    }
+    let opaque = tcx.hir().expect_opaque_ty(def_id);
+    matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
 }
 
 fn rendered_precise_capturing_args<'tcx>(
@@ -1870,12 +1866,10 @@ fn rendered_precise_capturing_args<'tcx>(
         return tcx.rendered_precise_capturing_args(opaque_def_id);
     }
 
-    tcx.hir_node_by_def_id(def_id).expect_item().expect_opaque_ty().bounds.iter().find_map(
-        |bound| match bound {
-            hir::GenericBound::Use(args, ..) => {
-                Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name())))
-            }
-            _ => None,
-        },
-    )
+    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| arg.name())))
+        }
+        _ => None,
+    })
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index d76d9213129..8648a7d1e32 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -1,4 +1,3 @@
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_hir::intravisit;
 use rustc_middle::hir::nested_filter::OnlyBodies;
@@ -10,12 +9,10 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
         return;
     }
 
-    for id in tcx.hir().items() {
-        let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue };
-
-        let ty = tcx.type_of(id.owner_id).instantiate_identity();
-
-        tcx.dcx().emit_err(crate::errors::TypeOf { span: tcx.def_span(id.owner_id), ty });
+    for id in tcx.hir_crate_items(()).opaques() {
+        let ty = tcx.type_of(id).instantiate_identity();
+        let span = tcx.def_span(id);
+        tcx.dcx().emit_err(crate::errors::TypeOf { span, ty });
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 8ff9640a874..14b6b17ed18 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -24,6 +24,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
         tcx.opt_rpitit_info(def_id.to_def_id())
     {
+        debug!("RPITIT fn_def_id={fn_def_id:?} opaque_def_id={opaque_def_id:?}");
         let trait_def_id = tcx.parent(fn_def_id);
         let opaque_ty_generics = tcx.generics_of(opaque_def_id);
         let opaque_ty_parent_count = opaque_ty_generics.parent_count;
@@ -207,36 +208,33 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
             Some(tcx.typeck_root_def_id(def_id.to_def_id()))
         }
-        Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(&hir::OpaqueTy {
-                origin:
-                    hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, in_trait_or_impl }
-                    | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
-                ..
-            }) => {
-                if in_trait_or_impl.is_some() {
-                    assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn);
-                } else {
-                    assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn);
-                }
-                Some(fn_def_id.to_def_id())
+        Node::OpaqueTy(&hir::OpaqueTy {
+            origin:
+                hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, in_trait_or_impl }
+                | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, in_trait_or_impl },
+            ..
+        }) => {
+            if in_trait_or_impl.is_some() {
+                assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn);
+            } else {
+                assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn);
             }
-            ItemKind::OpaqueTy(&hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty },
-                ..
-            }) => {
-                if in_assoc_ty {
-                    assert_matches!(tcx.def_kind(parent), DefKind::AssocTy);
-                } else {
-                    assert_matches!(tcx.def_kind(parent), DefKind::TyAlias);
-                }
-                debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent);
-                // Opaque types are always nested within another item, and
-                // inherit the generics of the item.
-                Some(parent.to_def_id())
+            Some(fn_def_id.to_def_id())
+        }
+        Node::OpaqueTy(&hir::OpaqueTy {
+            origin: hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty },
+            ..
+        }) => {
+            if in_assoc_ty {
+                assert_matches!(tcx.def_kind(parent), DefKind::AssocTy);
+            } else {
+                assert_matches!(tcx.def_kind(parent), DefKind::TyAlias);
             }
-            _ => None,
-        },
+            debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent);
+            // Opaque types are always nested within another item, and
+            // inherit the generics of the item.
+            Some(parent.to_def_id())
+        }
         _ => None,
     };
 
@@ -272,13 +270,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 ItemKind::TyAlias(..)
                 | ItemKind::Enum(..)
                 | ItemKind::Struct(..)
-                | ItemKind::OpaqueTy(..)
                 | ItemKind::Union(..) => (None, Defaults::Allowed),
                 ItemKind::Const(..) => (None, Defaults::Deny),
                 _ => (None, Defaults::FutureCompatDisallowed),
             }
         }
 
+        Node::OpaqueTy(..) => (None, Defaults::Allowed),
+
         // GATs
         Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
             (None, Defaults::Deny)
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 2418037ae96..4346504450d 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -335,8 +335,7 @@ pub(super) fn explicit_item_bounds_with_filter(
         // RPITIT's bounds are the same as opaque type bounds, but with
         // a projection self type.
         Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
-            let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item();
-            let opaque_ty = item.expect_opaque_ty();
+            let opaque_ty = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_opaque_ty();
             let item_ty = Ty::new_projection_from_args(
                 tcx,
                 def_id.to_def_id(),
@@ -347,7 +346,7 @@ pub(super) fn explicit_item_bounds_with_filter(
                 opaque_def_id.expect_local(),
                 opaque_ty.bounds,
                 item_ty,
-                item.span,
+                opaque_ty.span,
                 filter,
             );
             assert_only_contains_predicates_from(filter, bounds, item_ty);
@@ -369,11 +368,7 @@ pub(super) fn explicit_item_bounds_with_filter(
             span,
             ..
         }) => associated_type_bounds(tcx, def_id, bounds, *span, filter),
-        hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, origin, .. }),
-            span,
-            ..
-        }) => match origin {
+        hir::Node::OpaqueTy(hir::OpaqueTy { bounds, origin, span, .. }) => match origin {
             // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`,
             // when we're asking for the item bounds of the *opaques* in a trait's default
             // method signature, we need to map these projections back to opaques.
@@ -412,7 +407,7 @@ pub(super) fn explicit_item_bounds_with_filter(
             }
         },
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
-        _ => bug!("item_bounds called on {:?}", def_id),
+        node => bug!("item_bounds called on {def_id:?} => {node:?}"),
     };
 
     ty::EarlyBinder::bind(bounds)
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 33f6623edfd..6d30f7c7b9d 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -330,7 +330,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // Opaque types duplicate some of their generic parameters.
     // We create bi-directional Outlives predicates between the original
     // and the duplicated parameter, to ensure that they do not get out of sync.
-    if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
+    if let Node::OpaqueTy(..) = node {
         let opaque_ty_node = tcx.parent_hir_node(hir_id);
         let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes), .. }) = opaque_ty_node
         else {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index a15621bf28b..c8852a3a369 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -11,10 +11,13 @@ use std::fmt;
 
 use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::sorted_map::SortedMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
+use rustc_hir::{
+    GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, LifetimeName, Node,
+};
 use rustc_macros::extension;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
@@ -74,7 +77,7 @@ impl ResolvedArg {
 struct NamedVarMap {
     // maps from every use of a named (not anonymous) bound var to a
     // `ResolvedArg` describing how that variable is bound
-    defs: HirIdMap<ResolvedArg>,
+    defs: ItemLocalMap<ResolvedArg>,
 
     // Maps relevant hir items to the bound vars on them. These include:
     // - function defs
@@ -82,7 +85,7 @@ struct NamedVarMap {
     // - closures
     // - trait refs
     // - bound types (like `T` in `for<'a> T<'a>: Foo`)
-    late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
+    late_bound_vars: ItemLocalMap<Vec<ty::BoundVariableKind>>,
 }
 
 struct BoundVarContext<'a, 'tcx> {
@@ -225,10 +228,10 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         resolve_bound_vars,
 
-        named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
+        named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs,
         is_late_bound_map,
         object_lifetime_default,
-        late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
+        late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars,
 
         ..*providers
     };
@@ -265,16 +268,12 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
         hir::OwnerNode::Synthetic => unreachable!(),
     }
 
-    let mut rl = ResolveBoundVars::default();
-
-    for (hir_id, v) in named_variable_map.defs {
-        let map = rl.defs.entry(hir_id.owner).or_default();
-        map.insert(hir_id.local_id, v);
-    }
-    for (hir_id, v) in named_variable_map.late_bound_vars {
-        let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
-        map.insert(hir_id.local_id, v);
-    }
+    let defs = named_variable_map.defs.into_sorted_stable_ord();
+    let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord();
+    let rl = ResolveBoundVars {
+        defs: SortedMap::from_presorted_elements(defs),
+        late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars),
+    };
 
     debug!(?rl.defs);
     debug!(?rl.late_bound_vars);
@@ -340,7 +339,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Binder { hir_id, .. } => {
                     // Nested poly trait refs have the binders concatenated
                     let mut full_binders =
-                        self.map.late_bound_vars.entry(*hir_id).or_default().clone();
+                        self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone();
                     full_binders.extend(supertrait_bound_vars);
                     break (full_binders, BinderScopeType::Concatenating);
                 }
@@ -487,6 +486,31 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
+    fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
+        // We want to start our early-bound indices at the end of the parent scope,
+        // not including any parent `impl Trait`s.
+        let mut bound_vars = FxIndexMap::default();
+        debug!(?opaque.generics.params);
+        for param in opaque.generics.params {
+            let (def_id, reg) = ResolvedArg::early(param);
+            bound_vars.insert(def_id, reg);
+        }
+
+        let hir_id = self.tcx.local_def_id_to_hir_id(opaque.def_id);
+        let scope = Scope::Binder {
+            hir_id,
+            bound_vars,
+            s: self.scope,
+            scope_type: BinderScopeType::Normal,
+            where_bound_origin: None,
+        };
+        self.with(scope, |this| {
+            let scope = Scope::TraitRefBoundary { s: this.scope };
+            this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque))
+        })
+    }
+
+    #[instrument(level = "debug", skip(self))]
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         match &item.kind {
             hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
@@ -513,38 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
             }
-            hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
-                origin:
-                    hir::OpaqueTyOrigin::FnReturn { parent, .. }
-                    | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
-                    | hir::OpaqueTyOrigin::TyAlias { parent, .. },
-                generics,
-                ..
-            }) => {
-                // We want to start our early-bound indices at the end of the parent scope,
-                // not including any parent `impl Trait`s.
-                let mut bound_vars = FxIndexMap::default();
-                debug!(?generics.params);
-                for param in generics.params {
-                    let (def_id, reg) = ResolvedArg::early(param);
-                    bound_vars.insert(def_id, reg);
-                }
-
-                let scope = Scope::Root { opt_parent_item: Some(parent) };
-                self.with(scope, |this| {
-                    let scope = Scope::Binder {
-                        hir_id: item.hir_id(),
-                        bound_vars,
-                        s: this.scope,
-                        scope_type: BinderScopeType::Normal,
-                        where_bound_origin: None,
-                    };
-                    this.with(scope, |this| {
-                        let scope = Scope::TraitRefBoundary { s: this.scope };
-                        this.with(scope, |this| intravisit::walk_item(this, item))
-                    });
-                })
-            }
             hir::ItemKind::TyAlias(_, generics)
             | hir::ItemKind::Const(_, generics, _)
             | hir::ItemKind::Enum(_, generics)
@@ -684,22 +676,19 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             hir::TyKind::Ref(lifetime_ref, ref mt) => {
                 self.visit_lifetime(lifetime_ref);
                 let scope = Scope::ObjectLifetimeDefault {
-                    lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
+                    lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
                     s: self.scope,
                 };
                 self.with(scope, |this| this.visit_ty(mt.ty));
             }
-            hir::TyKind::OpaqueDef(item_id, lifetimes) => {
+            hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
+                self.visit_opaque_ty(opaque_ty);
+
                 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
                 //                 ^                  ^ this gets resolved in the scope of
                 //                                      the opaque_ty generics
-                let opaque_ty = self.tcx.hir().item(item_id);
-                match &opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: _, .. }) => {}
-                    i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
-                };
 
                 // Resolve the lifetimes that are applied to the opaque type.
                 // These are resolved in the current scope.
@@ -714,7 +703,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     // and ban them. Type variables instantiated inside binders aren't
                     // well-supported at the moment, so this doesn't work.
                     // In the future, this should be fixed and this error should be removed.
-                    let def = self.map.defs.get(&lifetime.hir_id).copied();
+                    let def = self.map.defs.get(&lifetime.hir_id.local_id).copied();
                     let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
                     let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
 
@@ -722,9 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     {
                         // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
                         // it must be a reified late-bound lifetime from a trait goal.
-                        hir::Node::Item(hir::Item {
-                            kind: hir::ItemKind::OpaqueTy { .. }, ..
-                        }) => "higher-ranked lifetime from outer `impl Trait`",
+                        hir::Node::OpaqueTy(_) => "higher-ranked lifetime from outer `impl Trait`",
                         // Other items are fine.
                         hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => {
                             continue;
@@ -740,8 +727,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
 
                     let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id)
                     {
-                        let opaque_span = self.tcx.def_span(item_id.owner_id);
-                        (opaque_span, Some(opaque_span))
+                        (opaque_ty.span, Some(opaque_ty.span))
                     } else {
                         (lifetime.ident.span, None)
                     };
@@ -854,7 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             let bound_vars: Vec<_> =
                 self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
             let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-            self.map.late_bound_vars.insert(hir_id, bound_vars);
+            self.map.late_bound_vars.insert(hir_id.local_id, bound_vars);
         }
         self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
         intravisit::walk_fn_kind(self, fk);
@@ -1032,10 +1018,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     }
 
     fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
-        if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
+        if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) {
             bug!(
                 "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
-                self.map.late_bound_vars[&hir_id]
+                self.map.late_bound_vars[&hir_id.local_id]
             )
         }
     }
@@ -1394,9 +1380,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         kind.descr(param_def_id.to_def_id())
                     ),
                 };
-                self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+                self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
             } else {
-                self.map.defs.insert(hir_id, def);
+                self.map.defs.insert(hir_id.local_id, def);
             }
             return;
         }
@@ -1429,7 +1415,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                             bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
                         }
                     });
-                    self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+                    self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar));
                     return;
                 }
                 Scope::Root { .. } => break,
@@ -1539,7 +1525,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     // This index can be used with `generic_args` since `parent_count == 0`.
                     let index = generics.param_def_id_to_index[&param_def_id] as usize;
                     generic_args.args.get(index).and_then(|arg| match arg {
-                        GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
+                        GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id.local_id).copied(),
                         _ => None,
                     })
                 }
@@ -1829,7 +1815,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
         debug!(span = ?lifetime_ref.ident.span);
-        self.map.defs.insert(lifetime_ref.hir_id, def);
+        self.map.defs.insert(lifetime_ref.hir_id.local_id, def);
     }
 
     /// Sometimes we resolve a lifetime, but later find that it is an
@@ -1840,8 +1826,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         lifetime_ref: &'tcx hir::Lifetime,
         bad_def: ResolvedArg,
     ) {
-        // FIXME(#120456) - is `swap_remove` correct?
-        let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id);
+        let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id);
         assert_eq!(old_value, Some(bad_def));
     }
 
@@ -2011,7 +1996,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
         // And this is exercised in:
         // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
-        let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap();
+        let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap();
         let existing_bound_vars_saved = existing_bound_vars.clone();
         existing_bound_vars.extend(bound_vars);
         self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3af4d1f5eda..470bcaeded1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -529,10 +529,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                 let args = ty::GenericArgs::identity_for_item(tcx, def_id);
                 Ty::new_adt(tcx, def, args)
             }
-            ItemKind::OpaqueTy(..) => tcx.type_of_opaque(def_id).map_or_else(
-                |CyclePlaceholder(guar)| Ty::new_error(tcx, guar),
-                |ty| ty.instantiate_identity(),
-            ),
             ItemKind::Trait(..)
             | ItemKind::TraitAlias(..)
             | ItemKind::Macro(..)
@@ -545,6 +541,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
             }
         },
 
+        Node::OpaqueTy(..) => tcx.type_of_opaque(def_id).map_or_else(
+            |CyclePlaceholder(guar)| Ty::new_error(tcx, guar),
+            |ty| ty.instantiate_identity(),
+        ),
+
         Node::ForeignItem(foreign_item) => match foreign_item.kind {
             ForeignItemKind::Fn(..) => {
                 let args = ty::GenericArgs::identity_for_item(tcx, def_id);
@@ -603,42 +604,25 @@ pub(super) fn type_of_opaque(
     def_id: DefId,
 ) -> Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
     if let Some(def_id) = def_id.as_local() {
-        use rustc_hir::*;
-
-        Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) {
-            Node::Item(item) => match item.kind {
-                ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. },
-                    ..
-                }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
-                ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. },
-                    ..
-                }) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id),
-                // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(&OpaqueTy {
-                    origin:
-                        hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
-                        | hir::OpaqueTyOrigin::AsyncFn { parent: owner, in_trait_or_impl },
-                    ..
-                }) => {
-                    if in_trait_or_impl == Some(hir::RpitContext::Trait)
-                        && !tcx.defaultness(owner).has_value()
-                    {
-                        span_bug!(
-                            tcx.def_span(def_id),
-                            "tried to get type of this RPITIT with no definition"
-                        );
-                    }
-                    opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
-                }
-                _ => {
-                    span_bug!(item.span, "type_of_opaque: unexpected item type: {:?}", item.kind);
+        Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
+            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
+                opaque::find_opaque_ty_constraints_for_tait(tcx, def_id)
+            }
+            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. } => {
+                opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id)
+            }
+            // Opaque types desugared from `impl Trait`.
+            hir::OpaqueTyOrigin::FnReturn { parent: owner, in_trait_or_impl }
+            | hir::OpaqueTyOrigin::AsyncFn { parent: owner, in_trait_or_impl } => {
+                if in_trait_or_impl == Some(hir::RpitContext::Trait)
+                    && !tcx.defaultness(owner).has_value()
+                {
+                    span_bug!(
+                        tcx.def_span(def_id),
+                        "tried to get type of this RPITIT with no definition"
+                    );
                 }
-            },
-
-            x => {
-                bug!("unexpected sort of node in type_of_opaque(): {:?}", x);
+                opaque::find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
             }
         }))
     } else {
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 95f83836d75..28a1fc88741 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2087,43 +2087,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
                 self.lower_path(opt_self_ty, path, hir_ty.hir_id, false)
             }
-            &hir::TyKind::OpaqueDef(item_id, lifetimes) => {
-                let opaque_ty = tcx.hir().item(item_id);
-
-                match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => {
-                        let local_def_id = item_id.owner_id.def_id;
-                        // 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.
-                        match origin {
-                            hir::OpaqueTyOrigin::FnReturn {
-                                in_trait_or_impl: Some(hir::RpitContext::Trait),
-                                ..
-                            }
-                            | hir::OpaqueTyOrigin::AsyncFn {
-                                in_trait_or_impl: Some(hir::RpitContext::Trait),
-                                ..
-                            } => self.lower_opaque_ty(
-                                tcx.associated_type_for_impl_trait_in_trait(local_def_id)
-                                    .to_def_id(),
-                                lifetimes,
-                                true,
-                            ),
-                            hir::OpaqueTyOrigin::FnReturn {
-                                in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
-                                ..
-                            }
-                            | hir::OpaqueTyOrigin::AsyncFn {
-                                in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
-                                ..
-                            }
-                            | hir::OpaqueTyOrigin::TyAlias { .. } => {
-                                self.lower_opaque_ty(local_def_id.to_def_id(), lifetimes, false)
-                            }
-                        }
+            &hir::TyKind::OpaqueDef(opaque_ty, lifetimes) => {
+                let local_def_id = opaque_ty.def_id;
+
+                // 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.
+                match opaque_ty.origin {
+                    hir::OpaqueTyOrigin::FnReturn {
+                        in_trait_or_impl: Some(hir::RpitContext::Trait),
+                        ..
+                    }
+                    | hir::OpaqueTyOrigin::AsyncFn {
+                        in_trait_or_impl: Some(hir::RpitContext::Trait),
+                        ..
+                    } => self.lower_opaque_ty(
+                        tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id(),
+                        lifetimes,
+                        true,
+                    ),
+                    hir::OpaqueTyOrigin::FnReturn {
+                        in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
+                        ..
+                    }
+                    | hir::OpaqueTyOrigin::AsyncFn {
+                        in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
+                        ..
+                    }
+                    | hir::OpaqueTyOrigin::TyAlias { .. } => {
+                        self.lower_opaque_ty(local_def_id.to_def_id(), lifetimes, false)
                     }
-                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 }
             }
             // If we encounter a type relative path with RTN generics, then it must have
@@ -2289,7 +2282,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     span_bug!(
                         tcx.def_span(param.def_id),
                         "only expected lifetime for opaque's own generics, got {:?}",
-                        param.kind
+                        param
                     );
                 };
                 let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else {
diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs
index dbaf9c2c6f0..a0fdf95a831 100644
--- a/compiler/rustc_hir_analysis/src/variance/dump.rs
+++ b/compiler/rustc_hir_analysis/src/variance/dump.rs
@@ -1,6 +1,5 @@
 use std::fmt::Write;
 
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_middle::ty::{GenericArgs, TyCtxt};
 use rustc_span::symbol::sym;
@@ -24,18 +23,18 @@ fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String {
 }
 
 pub(crate) fn variances(tcx: TyCtxt<'_>) {
-    if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) {
-        for id in tcx.hir().items() {
-            let DefKind::OpaqueTy = tcx.def_kind(id.owner_id) else { continue };
+    let crate_items = tcx.hir_crate_items(());
 
+    if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) {
+        for id in crate_items.opaques() {
             tcx.dcx().emit_err(crate::errors::VariancesOf {
-                span: tcx.def_span(id.owner_id),
-                variances: format_variances(tcx, id.owner_id.def_id),
+                span: tcx.def_span(id),
+                variances: format_variances(tcx, id),
             });
         }
     }
 
-    for id in tcx.hir().items() {
+    for id in crate_items.free_items() {
         if !tcx.has_attr(id.owner_id, sym::rustc_variance) {
             continue;
         }