From 03dff82d598233d4f1193d763f73c71a76ad6187 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 18:26:47 +0000
Subject: [PATCH 1/9] Add `of_trait` to DefKind::Impl.

---
 .../rustc_borrowck/src/diagnostics/mod.rs     | 14 +++++-----
 .../src/diagnostics/region_name.rs            |  4 +--
 .../src/const_eval/fn_queries.rs              |  3 +-
 compiler/rustc_hir/src/def.rs                 | 12 ++++----
 compiler/rustc_hir/src/target.rs              |  2 +-
 .../rustc_hir_analysis/src/check/check.rs     | 28 ++++++++++---------
 .../src/coherence/inherent_impls.rs           |  2 +-
 .../src/collect/lifetimes.rs                  |  2 +-
 .../rustc_hir_analysis/src/impl_wf_check.rs   |  2 +-
 .../infer/error_reporting/need_type_info.rs   |  2 +-
 compiler/rustc_metadata/src/rmeta/encoder.rs  | 16 +++++------
 compiler/rustc_metadata/src/rmeta/table.rs    |  3 +-
 compiler/rustc_middle/src/hir/map/mod.rs      |  2 +-
 compiler/rustc_middle/src/ty/mod.rs           |  2 +-
 compiler/rustc_middle/src/ty/util.rs          |  2 +-
 compiler/rustc_monomorphize/src/collector.rs  |  2 +-
 .../rustc_monomorphize/src/polymorphize.rs    |  2 +-
 compiler/rustc_passes/src/dead.rs             |  8 ++----
 compiler/rustc_passes/src/liveness.rs         |  2 +-
 compiler/rustc_passes/src/reachable.rs        |  2 +-
 compiler/rustc_privacy/src/lib.rs             |  4 +--
 .../rustc_resolve/src/build_reduced_graph.rs  |  2 +-
 compiler/rustc_save_analysis/src/lib.rs       |  2 +-
 compiler/rustc_ty_utils/src/implied_bounds.rs |  2 +-
 src/librustdoc/formats/item_type.rs           |  2 +-
 .../passes/collect_intra_doc_links.rs         |  4 +--
 .../clippy_lints/src/same_name_method.rs      |  2 +-
 src/tools/clippy/clippy_utils/src/lib.rs      |  2 +-
 28 files changed, 68 insertions(+), 64 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 3006e27e1d5b5..a89643fcfd484 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1182,13 +1182,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                     }
                     let parent_did = tcx.parent(method_did);
-                    let parent_self_ty = (tcx.def_kind(parent_did)
-                        == rustc_hir::def::DefKind::Impl)
-                        .then_some(parent_did)
-                        .and_then(|did| match tcx.type_of(did).kind() {
-                            ty::Adt(def, ..) => Some(def.did()),
-                            _ => None,
-                        });
+                    let parent_self_ty =
+                        matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
+                            .then_some(parent_did)
+                            .and_then(|did| match tcx.type_of(did).kind() {
+                                ty::Adt(def, ..) => Some(def.did()),
+                                _ => None,
+                            });
                     let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
                         matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                     });
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 237e063d8d11f..a82e695d64905 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -852,9 +852,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
 
         let tcx = self.infcx.tcx;
         let region_parent = tcx.parent(region.def_id);
-        if tcx.def_kind(region_parent) != DefKind::Impl {
+        let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
             return None;
-        }
+        };
 
         let found = tcx
             .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index f92277b111374..9eaab1f47a7ea 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -17,7 +17,8 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
 
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     let parent_id = tcx.local_parent(def_id);
-    tcx.def_kind(parent_id) == DefKind::Impl && tcx.constness(parent_id) == hir::Constness::Const
+    matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
+        && tcx.constness(parent_id) == hir::Constness::Const
 }
 
 /// Checks whether an item is considered to be `const`. If it is a constructor, it is const. If
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index f1801a0f844f7..0599ae04a90ab 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -116,7 +116,9 @@ pub enum DefKind {
     LifetimeParam,
     /// A use of `global_asm!`.
     GlobalAsm,
-    Impl,
+    Impl {
+        of_trait: bool,
+    },
     Closure,
     Generator,
 }
@@ -155,7 +157,7 @@ impl DefKind {
             DefKind::AnonConst => "constant expression",
             DefKind::InlineConst => "inline constant",
             DefKind::Field => "field",
-            DefKind::Impl => "implementation",
+            DefKind::Impl { .. } => "implementation",
             DefKind::Closure => "closure",
             DefKind::Generator => "generator",
             DefKind::ExternCrate => "extern crate",
@@ -171,7 +173,7 @@ impl DefKind {
             | DefKind::AssocFn
             | DefKind::Enum
             | DefKind::OpaqueTy
-            | DefKind::Impl
+            | DefKind::Impl { .. }
             | DefKind::Use
             | DefKind::InlineConst
             | DefKind::ExternCrate => "an",
@@ -216,7 +218,7 @@ impl DefKind {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::GlobalAsm
-            | DefKind::Impl
+            | DefKind::Impl { .. }
             | DefKind::ImplTraitPlaceholder => None,
         }
     }
@@ -255,7 +257,7 @@ impl DefKind {
             | DefKind::ForeignMod
             | DefKind::OpaqueTy
             | DefKind::ImplTraitPlaceholder
-            | DefKind::Impl
+            | DefKind::Impl { .. }
             | DefKind::Field
             | DefKind::TyParam
             | DefKind::ConstParam
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 5917d5e346e37..961deac544a88 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -116,7 +116,7 @@ impl Target {
             DefKind::Union => Target::Union,
             DefKind::Trait => Target::Trait,
             DefKind::TraitAlias => Target::TraitAlias,
-            DefKind::Impl => Target::Impl,
+            DefKind::Impl { .. } => Target::Impl,
             _ => panic!("impossible case reached"),
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 15a66ccc0f412..02d7c7e9d8499 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -529,19 +529,21 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             check_enum(tcx, id.owner_id.def_id);
         }
         DefKind::Fn => {} // entirely within check_item_body
-        DefKind::Impl => {
-            let it = tcx.hir().item(id);
-            let hir::ItemKind::Impl(impl_) = it.kind else { return };
-            debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
-            if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
-                check_impl_items_against_trait(
-                    tcx,
-                    it.span,
-                    it.owner_id.def_id,
-                    impl_trait_ref.subst_identity(),
-                    &impl_.items,
-                );
-                check_on_unimplemented(tcx, it);
+        DefKind::Impl { of_trait } => {
+            if of_trait {
+                let it = tcx.hir().item(id);
+                let hir::ItemKind::Impl(impl_) = it.kind else { return };
+                debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
+                if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
+                    check_impl_items_against_trait(
+                        tcx,
+                        it.span,
+                        it.owner_id.def_id,
+                        impl_trait_ref.subst_identity(),
+                        &impl_.items,
+                    );
+                    check_on_unimplemented(tcx, it);
+                }
             }
         }
         DefKind::Trait => {
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 940a450101ca0..2d2ac4f61947b 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -177,7 +177,7 @@ impl<'tcx> InherentCollect<'tcx> {
     }
 
     fn check_item(&mut self, id: hir::ItemId) {
-        if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) {
+        if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
             return;
         }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index 3f8d620fe6934..d8606f759b24b 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -1563,7 +1563,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             // See issue #83753. If someone writes an associated type on a non-trait, just treat it as
             // there being no supertrait HRTBs.
             match tcx.def_kind(def_id) {
-                DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
+                DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
                 _ => break None,
             }
 
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 4fe893442b9bd..4f30318412d7e 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -55,7 +55,7 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let min_specialization = tcx.features().min_specialization;
     let module = tcx.hir_module_items(module_def_id);
     for id in module.items() {
-        if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+        if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
             enforce_impl_params_are_constrained(tcx, id.owner_id.def_id);
             if min_specialization {
                 check_min_specialization(tcx, id.owner_id.def_id);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index c092efbb557cf..2b5a19914a327 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
                 };
 
                 let parent_def_id = generics.parent.unwrap();
-                if tcx.def_kind(parent_def_id) == DefKind::Impl {
+                if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
                     let parent_ty = tcx.bound_type_of(parent_def_id).subst(tcx, substs);
                     match (parent_ty.kind(), &ty.kind) {
                         (
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 060ade8a42f71..43047051f0f65 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -838,7 +838,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::ForeignMod
         | DefKind::OpaqueTy
         | DefKind::ImplTraitPlaceholder
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::Field => true,
         DefKind::TyParam
         | DefKind::ConstParam
@@ -873,7 +873,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         | DefKind::ImplTraitPlaceholder
         | DefKind::Enum
         | DefKind::Union
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::Trait
         | DefKind::TraitAlias
         | DefKind::Macro(..)
@@ -951,7 +951,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Const
         | DefKind::ForeignMod
         | DefKind::TyAlias
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::Trait
         | DefKind::TraitAlias
         | DefKind::Macro(..)
@@ -988,7 +988,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::ImplTraitPlaceholder
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::Field
         | DefKind::TyParam
         | DefKind::Closure
@@ -1018,7 +1018,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::TyAlias
         | DefKind::OpaqueTy
         | DefKind::ForeignTy
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::AssocFn
         | DefKind::AssocConst
         | DefKind::Closure
@@ -1081,7 +1081,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
         | DefKind::OpaqueTy
         | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
-        | DefKind::Impl
+        | DefKind::Impl { .. }
         | DefKind::AssocFn
         | DefKind::Closure
         | DefKind::Generator
@@ -1860,7 +1860,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             FxHashMap::default();
 
         for id in tcx.hir().items() {
-            if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+            if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
                 if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
                     let trait_ref = trait_ref.subst_identity();
 
@@ -2261,7 +2261,7 @@ pub fn provide(providers: &mut Providers) {
 
             let mut trait_impls = Vec::new();
             for id in tcx.hir().items() {
-                if matches!(tcx.def_kind(id.owner_id), DefKind::Impl)
+                if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
                     && tcx.impl_trait_ref(id.owner_id).is_some()
                 {
                     trait_impls.push(id.owner_id.to_def_id())
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 99bec570600a0..b89d48ec15ae9 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -136,7 +136,8 @@ fixed_size_enum! {
         ( Field                                    )
         ( LifetimeParam                            )
         ( GlobalAsm                                )
-        ( Impl                                     )
+        ( Impl { of_trait: false }                 )
+        ( Impl { of_trait: true }                  )
         ( Closure                                  )
         ( Generator                                )
         ( Static(ast::Mutability::Not)             )
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 7f2994fd79b98..ba93330d58120 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -203,7 +203,7 @@ impl<'hir> Map<'hir> {
                 ItemKind::Use(..) => DefKind::Use,
                 ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
                 ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
-                ItemKind::Impl { .. } => DefKind::Impl,
+                ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() },
             },
             Node::ForeignItem(item) => match item.kind {
                 ForeignItemKind::Fn(..) => DefKind::Fn,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6d8c9d7376333..e49c6062b3354 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2427,7 +2427,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
             let parent = self.parent(def_id);
-            if let DefKind::Impl = self.def_kind(parent) {
+            if let DefKind::Impl { .. } = self.def_kind(parent) {
                 return Some(parent);
             }
         }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index e907ce46c86fb..35831ff870642 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -167,7 +167,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 | DefKind::Fn
                 | DefKind::AssocFn
                 | DefKind::AssocConst
-                | DefKind::Impl,
+                | DefKind::Impl { .. },
                 def_id,
             ) => Some(def_id),
             Res::Err => None,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 83b8988cecaf8..8f6338472df58 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1238,7 +1238,7 @@ impl<'v> RootCollector<'_, 'v> {
                     collect_const_value(self.tcx, val, &mut self.output);
                 }
             }
-            DefKind::Impl => {
+            DefKind::Impl { .. } => {
                 if self.mode == MonoItemCollectionMode::Eager {
                     let item = self.tcx.hir().item(id);
                     create_mono_items_for_default_impls(self.tcx, item, self.output);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index aba842817ef7a..207ad332c22c2 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -172,7 +172,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
-        | DefKind::Impl => {
+        | DefKind::Impl { .. } => {
             for param in &generics.params {
                 debug!(?param, "(other)");
                 if let ty::GenericParamDefKind::Lifetime = param.kind {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 83adfeb6b10b6..fe0cb71d2c18d 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -526,10 +526,8 @@ fn check_item<'tcx>(
                 }
             }
         }
-        DefKind::Impl => {
-            let of_trait = tcx.impl_trait_ref(id.owner_id);
-
-            if of_trait.is_some() {
+        DefKind::Impl { of_trait } => {
+            if of_trait {
                 worklist.push(id.owner_id.def_id);
             }
 
@@ -541,7 +539,7 @@ fn check_item<'tcx>(
 
             // And we access the Map here to get HirId from LocalDefId
             for id in local_def_ids {
-                if of_trait.is_some() || has_allow_dead_code_or_lang_attr(tcx, id) {
+                if of_trait || has_allow_dead_code_or_lang_attr(tcx, id) {
                     worklist.push(id);
                 }
             }
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6afdcc37fe86e..678f1815d012c 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -145,7 +145,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
 
     // Don't run unused pass for #[derive()]
     let parent = tcx.local_parent(local_def_id);
-    if let DefKind::Impl = tcx.def_kind(parent)
+    if let DefKind::Impl { .. } = tcx.def_kind(parent)
         && tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
     {
         return;
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index ad09522038678..9559ee9320f5c 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -320,7 +320,7 @@ fn check_item<'tcx>(
         worklist.push(id.owner_id.def_id);
     }
 
-    if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+    if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: true }) {
         return;
     }
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9cff62e85146e..4675bd79c4629 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -593,7 +593,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             | DefKind::InlineConst
             | DefKind::Field
             | DefKind::GlobalAsm
-            | DefKind::Impl
+            | DefKind::Impl { .. }
             | DefKind::Closure
             | DefKind::Generator => (),
         }
@@ -1997,7 +1997,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
             // Subitems of inherent impls have their own publicity.
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
-            DefKind::Impl => {
+            DefKind::Impl { .. } => {
                 let item = tcx.hir().item(id);
                 if let hir::ItemKind::Impl(ref impl_) = item.kind {
                     let impl_vis =
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 44f3bf1be055d..e927ec9cb67ff 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -987,7 +987,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 | DefKind::LifetimeParam
                 | DefKind::GlobalAsm
                 | DefKind::Closure
-                | DefKind::Impl
+                | DefKind::Impl { .. }
                 | DefKind::Generator,
                 _,
             )
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index a9a92cc4f62ed..ad151bc2e1bf5 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -733,7 +733,7 @@ impl<'tcx> SaveContext<'tcx> {
                 | HirDefKind::Use
                 | HirDefKind::Field
                 | HirDefKind::GlobalAsm
-                | HirDefKind::Impl
+                | HirDefKind::Impl { .. }
                 | HirDefKind::Closure
                 | HirDefKind::Generator,
                 _,
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 961c04974e508..2fe9d135fa562 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -21,7 +21,7 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
             assumed_wf_types.extend(liberated_sig.inputs_and_output);
             tcx.intern_type_list(&assumed_wf_types)
         }
-        DefKind::Impl => {
+        DefKind::Impl { .. } => {
             match tcx.impl_trait_ref(def_id) {
                 Some(trait_ref) => {
                     let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index aafedc17499a7..452e14918faf7 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -140,7 +140,7 @@ impl From<DefKind> for ItemType {
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::GlobalAsm
-            | DefKind::Impl
+            | DefKind::Impl { .. }
             | DefKind::Closure
             | DefKind::Generator => Self::ForeignType,
         }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 7e3149a59e3af..b2208da9060dc 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -359,7 +359,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 _ => def_id,
             })
             .and_then(|self_id| match tcx.def_kind(self_id) {
-                DefKind::Impl => self.def_id_to_res(self_id),
+                DefKind::Impl { .. } => self.def_id_to_res(self_id),
                 DefKind::Use => None,
                 def_kind => Some(Res::Def(def_kind, self_id)),
             })
@@ -1761,7 +1761,7 @@ fn resolution_failure(
                             }
                             Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder
                             | TraitAlias | TyParam | Static(_) => "associated item",
-                            Impl | GlobalAsm => unreachable!("not a path"),
+                            Impl { .. } | GlobalAsm => unreachable!("not a path"),
                         }
                     } else {
                         "associated item"
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 17763128cd143..a37e2772d3558 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
         let mut map = FxHashMap::<Res, ExistingName>::default();
 
         for id in cx.tcx.hir().items() {
-            if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl)
+            if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl { .. })
                 && let item = cx.tcx.hir().item(id)
                 && let ItemKind::Impl(Impl {
                   items,
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 26f279f55855f..3b8713e2b108c 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -552,7 +552,7 @@ fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol)
             .filter(|item| item.ident.name == name)
             .map(|child| child.res.expect_non_local())
             .collect(),
-        DefKind::Impl => tcx
+        DefKind::Impl { .. } => tcx
             .associated_item_def_ids(def_id)
             .iter()
             .copied()

From 2a51e73ac9a1616300e3db93e094baa4b86b895f Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 18:31:04 +0000
Subject: [PATCH 2/9] Do not fetch HIR for inherent impls.

---
 .../src/coherence/inherent_impls.rs           | 92 ++++++++-----------
 1 file changed, 36 insertions(+), 56 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 2d2ac4f61947b..f0b6ab03ad693 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -14,7 +14,6 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use rustc_span::symbol::sym;
-use rustc_span::Span;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
 pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls {
@@ -57,86 +56,76 @@ const ADD_ATTR: &str =
     "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items";
 
 impl<'tcx> InherentCollect<'tcx> {
-    fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId, span: Span) {
-        let impl_def_id = item.owner_id;
-        if let Some(def_id) = def_id.as_local() {
+    fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) {
+        if let Some(ty_def_id) = ty_def_id.as_local() {
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
-            let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
+            let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default();
             vec.push(impl_def_id.to_def_id());
             return;
         }
 
         if self.tcx.features().rustc_attrs {
-            let hir::ItemKind::Impl(&hir::Impl { items, .. }) = item.kind else {
-                bug!("expected `impl` item: {:?}", item);
-            };
+            let items = self.tcx.associated_item_def_ids(impl_def_id);
 
-            if !self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
+            if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
+                let impl_span = self.tcx.def_span(impl_def_id);
                 struct_span_err!(
                     self.tcx.sess,
-                    span,
+                    impl_span,
                     E0390,
                     "cannot define inherent `impl` for a type outside of the crate where the type is defined",
                 )
                 .help(INTO_DEFINING_CRATE)
-                .span_help(span, ADD_ATTR_TO_TY)
+                .span_help(impl_span, ADD_ATTR_TO_TY)
                 .emit();
                 return;
             }
 
-            for impl_item in items {
-                if !self
-                    .tcx
-                    .has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
-                {
+            for &impl_item in items {
+                if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
+                    let impl_span = self.tcx.def_span(impl_def_id);
                     struct_span_err!(
                         self.tcx.sess,
-                        span,
+                        impl_span,
                         E0390,
                         "cannot define inherent `impl` for a type outside of the crate where the type is defined",
                     )
                     .help(INTO_DEFINING_CRATE)
-                    .span_help(self.tcx.hir().span(impl_item.id.hir_id()), ADD_ATTR)
+                    .span_help(self.tcx.def_span(impl_item), ADD_ATTR)
                     .emit();
                     return;
                 }
             }
 
             if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
-                self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id);
+                self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
             } else {
                 bug!("unexpected self type: {:?}", self_ty);
             }
         } else {
+            let impl_span = self.tcx.def_span(impl_def_id);
             struct_span_err!(
                 self.tcx.sess,
-                span,
+                impl_span,
                 E0116,
                 "cannot define inherent `impl` for a type outside of the crate \
                               where the type is defined"
             )
-            .span_label(span, "impl for type defined outside of crate.")
+            .span_label(impl_span, "impl for type defined outside of crate.")
             .note("define and implement a trait or new type instead")
             .emit();
         }
     }
 
-    fn check_primitive_impl(
-        &mut self,
-        impl_def_id: LocalDefId,
-        ty: Ty<'tcx>,
-        items: &[hir::ImplItemRef],
-        span: Span,
-    ) {
+    fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) {
+        let items = self.tcx.associated_item_def_ids(impl_def_id);
         if !self.tcx.hir().rustc_coherence_is_core() {
             if self.tcx.features().rustc_attrs {
-                for item in items {
-                    if !self
-                        .tcx
-                        .has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
-                    {
+                for &impl_item in items {
+                    if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
+                        let span = self.tcx.def_span(impl_def_id);
                         struct_span_err!(
                             self.tcx.sess,
                             span,
@@ -144,12 +133,13 @@ impl<'tcx> InherentCollect<'tcx> {
                             "cannot define inherent `impl` for primitive types outside of `core`",
                         )
                         .help(INTO_CORE)
-                        .span_help(item.span, ADD_ATTR)
+                        .span_help(self.tcx.def_span(impl_item), ADD_ATTR)
                         .emit();
                         return;
                     }
                 }
             } else {
+                let span = self.tcx.def_span(impl_def_id);
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     span,
@@ -181,31 +171,23 @@ impl<'tcx> InherentCollect<'tcx> {
             return;
         }
 
-        let item = self.tcx.hir().item(id);
-        let impl_span = self.tcx.hir().span(id.hir_id());
-        let hir::ItemKind::Impl(hir::Impl { of_trait: None, items, .. }) = item.kind else {
-            return;
-        };
-
-        let self_ty = self.tcx.type_of(item.owner_id);
+        let id = id.owner_id.def_id;
+        let item_span = self.tcx.def_span(id);
+        let self_ty = self.tcx.type_of(id);
         match *self_ty.kind() {
-            ty::Adt(def, _) => {
-                self.check_def_id(item, self_ty, def.did(), impl_span);
-            }
-            ty::Foreign(did) => {
-                self.check_def_id(item, self_ty, did, impl_span);
-            }
+            ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
+            ty::Foreign(did) => self.check_def_id(id, self_ty, did),
             ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
-                self.check_def_id(item, self_ty, data.principal_def_id().unwrap(), impl_span);
+                self.check_def_id(id, self_ty, data.principal_def_id().unwrap());
             }
             ty::Dynamic(..) => {
                 struct_span_err!(
                     self.tcx.sess,
-                    impl_span,
+                    item_span,
                     E0785,
                     "cannot define inherent `impl` for a dyn auto trait"
                 )
-                .span_label(impl_span, "impl requires at least one non-auto trait")
+                .span_label(item_span, "impl requires at least one non-auto trait")
                 .note("define and implement a new trait or type instead")
                 .emit();
             }
@@ -221,18 +203,16 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::Ref(..)
             | ty::Never
             | ty::FnPtr(_)
-            | ty::Tuple(..) => {
-                self.check_primitive_impl(item.owner_id.def_id, self_ty, items, impl_span)
-            }
+            | ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
             ty::Alias(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
-                    impl_span,
+                    item_span,
                     E0118,
                     "no nominal type found for inherent implementation"
                 );
 
-                err.span_label(impl_span, "impl requires a nominal type")
+                err.span_label(item_span, "impl requires a nominal type")
                     .note("either implement a trait on it or create a newtype to wrap it instead");
 
                 err.emit();
@@ -245,7 +225,7 @@ impl<'tcx> InherentCollect<'tcx> {
             | ty::Bound(..)
             | ty::Placeholder(_)
             | ty::Infer(_) => {
-                bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty);
+                bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
             }
             ty::Error(_) => {}
         }

From e9e12266ced4c43f07c53017f5ed094e93157a18 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 18:35:31 +0000
Subject: [PATCH 3/9] Do not fetch HIR for reachable.

---
 compiler/rustc_passes/src/reachable.rs | 29 ++++++++++++--------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 9559ee9320f5c..051100c56f813 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -325,26 +325,23 @@ fn check_item<'tcx>(
     }
 
     // We need only trait impls here, not inherent impls, and only non-exported ones
-    let item = tcx.hir().item(id);
-    if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
-        item.kind
-    {
-        if !effective_visibilities.is_reachable(item.owner_id.def_id) {
-            worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
+    if effective_visibilities.is_reachable(id.owner_id.def_id) {
+        return;
+    }
 
-            let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
-                unreachable!();
-            };
+    let items = tcx.associated_item_def_ids(id.owner_id);
+    worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local()));
 
-            if !trait_def_id.is_local() {
-                return;
-            }
+    let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else {
+        unreachable!();
+    };
 
-            worklist.extend(
-                tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()),
-            );
-        }
+    if !trait_def_id.is_local() {
+        return;
     }
+
+    worklist
+        .extend(tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()));
 }
 
 fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {

From facecf6e1b96f3dc1c2a3f1bcfb56caa018e78cf Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 18:49:54 +0000
Subject: [PATCH 4/9] Fetch less HIR in signature check.

---
 .../rustc_hir_analysis/src/check/check.rs     |  99 ++---
 .../src/check/compare_impl_item.rs            |  64 ++--
 compiler/rustc_hir_analysis/src/check/mod.rs  |  20 +-
 tests/rustdoc-ui/issue-105742.rs              |  21 -
 tests/rustdoc-ui/issue-105742.stderr          | 362 +-----------------
 tests/ui/error-codes/E0520.stderr             |   2 +-
 .../specialization-no-default.stderr          |  10 +-
 .../ui/specialization/issue-50452-fail.stderr |   2 +-
 .../non-defaulted-item-fail.stderr            |  12 +-
 .../specialization-no-default.stderr          |  10 +-
 .../ui/traits/negative-impls/no-items.stderr  |   2 +-
 11 files changed, 97 insertions(+), 507 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 02d7c7e9d8499..d5def62885043 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -530,46 +530,33 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
         }
         DefKind::Fn => {} // entirely within check_item_body
         DefKind::Impl { of_trait } => {
-            if of_trait {
-                let it = tcx.hir().item(id);
-                let hir::ItemKind::Impl(impl_) = it.kind else { return };
-                debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
-                if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
-                    check_impl_items_against_trait(
-                        tcx,
-                        it.span,
-                        it.owner_id.def_id,
-                        impl_trait_ref.subst_identity(),
-                        &impl_.items,
-                    );
-                    check_on_unimplemented(tcx, it);
-                }
+            if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(id.owner_id) {
+                check_impl_items_against_trait(
+                    tcx,
+                    id.owner_id.def_id,
+                    impl_trait_ref.subst_identity(),
+                );
+                check_on_unimplemented(tcx, id);
             }
         }
         DefKind::Trait => {
-            let it = tcx.hir().item(id);
-            let hir::ItemKind::Trait(_, _, _, _, items) = it.kind else {
-                return;
-            };
-            check_on_unimplemented(tcx, it);
-
-            for item in items.iter() {
-                let item = tcx.hir().trait_item(item.id);
-                match &item.kind {
-                    hir::TraitItemKind::Fn(sig, _) => {
-                        let abi = sig.header.abi;
-                        fn_maybe_err(tcx, item.ident.span, abi);
+            let assoc_items = tcx.associated_items(id.owner_id);
+            check_on_unimplemented(tcx, id);
+
+            for assoc_item in assoc_items.in_definition_order() {
+                match assoc_item.kind {
+                    ty::AssocKind::Fn => {
+                        let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
+                        fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
                     }
-                    hir::TraitItemKind::Type(.., Some(default)) => {
-                        let assoc_item = tcx.associated_item(item.owner_id);
+                    ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
                         let trait_substs =
-                            InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id());
+                            InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id());
                         let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
                             tcx,
                             assoc_item,
                             assoc_item,
-                            default.span,
-                            tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
+                            tcx.mk_trait_ref(id.owner_id.to_def_id(), trait_substs),
                         );
                     }
                     _ => {}
@@ -681,7 +668,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
     }
 }
 
-pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
+pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: hir::ItemId) {
     // an error would be reported if this fails.
     let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
 }
@@ -691,7 +678,7 @@ pub(super) fn check_specialization_validity<'tcx>(
     trait_def: &ty::TraitDef,
     trait_item: &ty::AssocItem,
     impl_id: DefId,
-    impl_item: &hir::ImplItemRef,
+    impl_item: DefId,
 ) {
     let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
     let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
@@ -737,10 +724,8 @@ pub(super) fn check_specialization_validity<'tcx>(
 
 fn check_impl_items_against_trait<'tcx>(
     tcx: TyCtxt<'tcx>,
-    full_impl_span: Span,
     impl_id: LocalDefId,
     impl_trait_ref: ty::TraitRef<'tcx>,
-    impl_item_refs: &[hir::ImplItemRef],
 ) {
     // If the trait reference itself is erroneous (so the compilation is going
     // to fail), skip checking the items here -- the `impl_item` table in `tcx`
@@ -749,12 +734,14 @@ fn check_impl_items_against_trait<'tcx>(
         return;
     }
 
+    let impl_item_refs = tcx.associated_item_def_ids(impl_id);
+
     // Negative impls are not expected to have any items
     match tcx.impl_polarity(impl_id) {
         ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
         ty::ImplPolarity::Negative => {
             if let [first_item_ref, ..] = impl_item_refs {
-                let first_item_span = tcx.hir().impl_item(first_item_ref.id).span;
+                let first_item_span = tcx.def_span(first_item_ref);
                 struct_span_err!(
                     tcx.sess,
                     first_item_span,
@@ -769,43 +756,27 @@ fn check_impl_items_against_trait<'tcx>(
 
     let trait_def = tcx.trait_def(impl_trait_ref.def_id);
 
-    for impl_item in impl_item_refs {
-        let ty_impl_item = tcx.associated_item(impl_item.id.owner_id);
+    for &impl_item in impl_item_refs {
+        let ty_impl_item = tcx.associated_item(impl_item);
         let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
             tcx.associated_item(trait_item_id)
         } else {
             // Checked in `associated_item`.
-            tcx.sess.delay_span_bug(impl_item.span, "missing associated item in trait");
+            tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait");
             continue;
         };
-        let impl_item_full = tcx.hir().impl_item(impl_item.id);
-        match impl_item_full.kind {
-            hir::ImplItemKind::Const(..) => {
+        match ty_impl_item.kind {
+            ty::AssocKind::Const => {
                 let _ = tcx.compare_impl_const((
-                    impl_item.id.owner_id.def_id,
+                    impl_item.expect_local(),
                     ty_impl_item.trait_item_def_id.unwrap(),
                 ));
             }
-            hir::ImplItemKind::Fn(..) => {
-                let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
-                compare_impl_method(
-                    tcx,
-                    &ty_impl_item,
-                    &ty_trait_item,
-                    impl_trait_ref,
-                    opt_trait_span,
-                );
+            ty::AssocKind::Fn => {
+                compare_impl_method(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
             }
-            hir::ImplItemKind::Type(impl_ty) => {
-                let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
-                compare_impl_ty(
-                    tcx,
-                    &ty_impl_item,
-                    impl_ty.span,
-                    &ty_trait_item,
-                    impl_trait_ref,
-                    opt_trait_span,
-                );
+            ty::AssocKind::Type => {
+                compare_impl_ty(tcx, &ty_impl_item, &ty_trait_item, impl_trait_ref);
             }
         }
 
@@ -840,6 +811,8 @@ fn check_impl_items_against_trait<'tcx>(
                 .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
 
             if !is_implemented_here {
+                let full_impl_span =
+                    tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
                 match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
                     EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
                         tcx,
@@ -866,6 +839,8 @@ fn check_impl_items_against_trait<'tcx>(
         }
 
         if !missing_items.is_empty() {
+            let full_impl_span =
+                tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
             missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
         }
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index a926deb2393de..50f9bbc022e7c 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -33,7 +33,6 @@ use std::iter;
 /// # Parameters
 ///
 /// - `impl_m`: type of the method we are checking
-/// - `impl_m_span`: span to use for reporting errors
 /// - `trait_m`: the method in the trait
 /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
 pub(super) fn compare_impl_method<'tcx>(
@@ -41,23 +40,19 @@ pub(super) fn compare_impl_method<'tcx>(
     impl_m: &ty::AssocItem,
     trait_m: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
-    trait_item_span: Option<Span>,
 ) {
     debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
 
-    let impl_m_span = tcx.def_span(impl_m.def_id);
-
     let _: Result<_, ErrorGuaranteed> = try {
-        compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)?;
-        compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false)?;
+        compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
+        compare_number_of_generics(tcx, impl_m, trait_m, false)?;
         compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
-        compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
+        compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
         compare_synthetic_generics(tcx, impl_m, trait_m)?;
-        compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
+        compare_asyncness(tcx, impl_m, trait_m)?;
         compare_method_predicate_entailment(
             tcx,
             impl_m,
-            impl_m_span,
             trait_m,
             impl_trait_ref,
             CheckImpliedWfMode::Check,
@@ -131,11 +126,10 @@ pub(super) fn compare_impl_method<'tcx>(
 ///
 /// Finally we register each of these predicates as an obligation and check that
 /// they hold.
-#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
+#[instrument(level = "debug", skip(tcx, impl_trait_ref))]
 fn compare_method_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
-    impl_m_span: Span,
     trait_m: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
     check_implied_wf: CheckImpliedWfMode,
@@ -148,6 +142,7 @@ fn compare_method_predicate_entailment<'tcx>(
     // FIXME(@lcnr): remove that after removing `cause.body_id` from
     // obligations.
     let impl_m_def_id = impl_m.def_id.expect_local();
+    let impl_m_span = tcx.def_span(impl_m_def_id);
     let cause = ObligationCause::new(
         impl_m_span,
         impl_m_def_id,
@@ -315,7 +310,6 @@ fn compare_method_predicate_entailment<'tcx>(
                 return compare_method_predicate_entailment(
                     tcx,
                     impl_m,
-                    impl_m_span,
                     trait_m,
                     impl_trait_ref,
                     CheckImpliedWfMode::Skip,
@@ -353,7 +347,6 @@ fn compare_method_predicate_entailment<'tcx>(
                 return compare_method_predicate_entailment(
                     tcx,
                     impl_m,
-                    impl_m_span,
                     trait_m,
                     impl_trait_ref,
                     CheckImpliedWfMode::Skip,
@@ -535,9 +528,7 @@ enum CheckImpliedWfMode {
 fn compare_asyncness<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
-    impl_m_span: Span,
     trait_m: &ty::AssocItem,
-    trait_item_span: Option<Span>,
 ) -> Result<(), ErrorGuaranteed> {
     if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
         match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -549,9 +540,9 @@ fn compare_asyncness<'tcx>(
             }
             _ => {
                 return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
-                    span: impl_m_span,
+                    span: tcx.def_span(impl_m.def_id),
                     method_name: trait_m.name,
-                    trait_item_span,
+                    trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
                 }));
             }
         };
@@ -606,7 +597,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
 
     // First, check a few of the same things as `compare_impl_method`,
     // just so we don't ICE during substitution later.
-    compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
+    compare_number_of_generics(tcx, impl_m, trait_m, true)?;
     compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
     check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
 
@@ -1094,7 +1085,6 @@ fn extract_spans_for_error_reporting<'tcx>(
 fn compare_self_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
-    impl_m_span: Span,
     trait_m: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
@@ -1130,6 +1120,7 @@ fn compare_self_type<'tcx>(
 
         (false, true) => {
             let self_descr = self_string(impl_m);
+            let impl_m_span = tcx.def_span(impl_m.def_id);
             let mut err = struct_span_err!(
                 tcx.sess,
                 impl_m_span,
@@ -1149,6 +1140,7 @@ fn compare_self_type<'tcx>(
 
         (true, false) => {
             let self_descr = self_string(trait_m);
+            let impl_m_span = tcx.def_span(impl_m.def_id);
             let mut err = struct_span_err!(
                 tcx.sess,
                 impl_m_span,
@@ -1196,7 +1188,6 @@ fn compare_number_of_generics<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_: &ty::AssocItem,
     trait_: &ty::AssocItem,
-    trait_span: Option<Span>,
     delay: bool,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
@@ -1256,6 +1247,7 @@ fn compare_number_of_generics<'tcx>(
                     .collect();
                 (Some(arg_spans), impl_trait_spans)
             } else {
+                let trait_span = tcx.hir().span_if_local(trait_.def_id);
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
@@ -1338,9 +1330,7 @@ fn compare_number_of_generics<'tcx>(
 fn compare_number_of_method_arguments<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
-    impl_m_span: Span,
     trait_m: &ty::AssocItem,
-    trait_item_span: Option<Span>,
 ) -> Result<(), ErrorGuaranteed> {
     let impl_m_fty = tcx.fn_sig(impl_m.def_id);
     let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1362,7 +1352,7 @@ fn compare_number_of_method_arguments<'tcx>(
                     }
                 })
             })
-            .or(trait_item_span);
+            .or_else(|| tcx.hir().span_if_local(trait_m.def_id));
 
         let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         let pos = impl_number_args.saturating_sub(1);
@@ -1377,7 +1367,7 @@ fn compare_number_of_method_arguments<'tcx>(
                     arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
                 }
             })
-            .unwrap_or(impl_m_span);
+            .unwrap_or_else(|| tcx.def_span(impl_m.def_id));
 
         let mut err = struct_span_err!(
             tcx.sess,
@@ -1747,22 +1737,16 @@ pub(super) fn compare_impl_const_raw(
 pub(super) fn compare_impl_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_ty: &ty::AssocItem,
-    impl_ty_span: Span,
     trait_ty: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
-    trait_item_span: Option<Span>,
 ) {
     debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
 
     let _: Result<(), ErrorGuaranteed> = try {
-        compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
-
+        compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
         compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
-
-        let sp = tcx.def_span(impl_ty.def_id);
-        compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
-
-        check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)?;
+        compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
+        check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
     };
 }
 
@@ -1771,7 +1755,6 @@ pub(super) fn compare_impl_ty<'tcx>(
 fn compare_type_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_ty: &ty::AssocItem,
-    impl_ty_span: Span,
     trait_ty: &ty::AssocItem,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
@@ -1808,6 +1791,7 @@ fn compare_type_predicate_entailment<'tcx>(
 
     debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
 
+    let impl_ty_span = tcx.def_span(impl_ty_def_id);
     let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
     let param_env = ty::ParamEnv::new(
         tcx.intern_predicates(&hybrid_preds.predicates),
@@ -1873,7 +1857,6 @@ pub(super) fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
     impl_ty: &ty::AssocItem,
-    impl_ty_span: Span,
     impl_trait_ref: ty::TraitRef<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     // Given
@@ -2009,8 +1992,15 @@ pub(super) fn check_type_bounds<'tcx>(
     let infcx = tcx.infer_ctxt().build();
     let ocx = ObligationCtxt::new(&infcx);
 
-    let assumed_wf_types =
-        ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
+    let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
+        hir::Node::TraitItem(hir::TraitItem {
+            kind: hir::TraitItemKind::Type(_, Some(ty)),
+            ..
+        }) => ty.span,
+        hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
+        _ => bug!(),
+    };
+    let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
 
     let normalize_cause = ObligationCause::new(
         impl_ty_span,
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index bec693439a46c..7b013cabc3ab5 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -75,7 +75,6 @@ pub use check::check_abi;
 use check::check_mod_item_types;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
@@ -169,27 +168,24 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
     }
 }
 
-fn report_forbidden_specialization(
-    tcx: TyCtxt<'_>,
-    impl_item: &hir::ImplItemRef,
-    parent_impl: DefId,
-) {
+fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
+    let span = tcx.def_span(impl_item);
+    let ident = tcx.item_name(impl_item);
     let mut err = struct_span_err!(
         tcx.sess,
-        impl_item.span,
+        span,
         E0520,
-        "`{}` specializes an item from a parent `impl`, but \
-         that item is not marked `default`",
-        impl_item.ident
+        "`{}` specializes an item from a parent `impl`, but that item is not marked `default`",
+        ident,
     );
-    err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
+    err.span_label(span, format!("cannot specialize default item `{}`", ident));
 
     match tcx.span_of_impl(parent_impl) {
         Ok(span) => {
             err.span_label(span, "parent `impl` is here");
             err.note(&format!(
                 "to specialize, `{}` in the parent `impl` must be marked `default`",
-                impl_item.ident
+                ident
             ));
         }
         Err(cname) => {
diff --git a/tests/rustdoc-ui/issue-105742.rs b/tests/rustdoc-ui/issue-105742.rs
index cb1de7433cfaa..9f36e5315ecc2 100644
--- a/tests/rustdoc-ui/issue-105742.rs
+++ b/tests/rustdoc-ui/issue-105742.rs
@@ -3,38 +3,17 @@
 use std::ops::Index;
 
 pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
     let _ = s;
 }
 
 pub trait SVec: Index<
     <Self as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
     Output = <Index<<Self as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
     Output = <Self as SVec>::Item> as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
-//~^^^^^ ERROR
-//~^^^^^^ ERROR
-//~^^^^^^^ ERROR
-//~^^^^^^^^ ERROR
 > {
     type Item<'a, T>;
 
     fn len(&self) -> <Self as SVec>::Item;
     //~^ ERROR
     //~^^ ERROR
-    //~^^^ ERROR
-    //~^^^^ ERROR
 }
diff --git a/tests/rustdoc-ui/issue-105742.stderr b/tests/rustdoc-ui/issue-105742.stderr
index ffb602cf86190..4d2ee97268917 100644
--- a/tests/rustdoc-ui/issue-105742.stderr
+++ b/tests/rustdoc-ui/issue-105742.stderr
@@ -1,360 +1,11 @@
 error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:13:21
-   |
-LL |     <Self as SVec>::Item,
-   |                     ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     <Self as SVec>::Item<'a>,
-   |                         ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:13:21
-   |
-LL |     <Self as SVec>::Item,
-   |                     ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     <Self as SVec>::Item<T>,
-   |                         +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:18:37
-   |
-LL |     Output = <Index<<Self as SVec>::Item,
-   |                                     ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Index<<Self as SVec>::Item<'a>,
-   |                                         ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:18:37
-   |
-LL |     Output = <Index<<Self as SVec>::Item,
-   |                                     ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Index<<Self as SVec>::Item<T>,
-   |                                         +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:30
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                              ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
-   |                                  ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:30
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                              ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
-   |                                  +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:46
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                                              ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
-   |                                                  ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:46
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                                              ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
-   |                                                  +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:5:40
-   |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
-   |                                        ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) {
-   |                                            ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:5:40
-   |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
-   |                                        ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) {
-   |                                            +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:13:21
-   |
-LL |     <Self as SVec>::Item,
-   |                     ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     <Self as SVec>::Item<'a>,
-   |                         ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:13:21
-   |
-LL |     <Self as SVec>::Item,
-   |                     ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     <Self as SVec>::Item<T>,
-   |                         +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:18:37
-   |
-LL |     Output = <Index<<Self as SVec>::Item,
-   |                                     ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Index<<Self as SVec>::Item<'a>,
-   |                                         ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:18:37
-   |
-LL |     Output = <Index<<Self as SVec>::Item,
-   |                                     ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Index<<Self as SVec>::Item<T>,
-   |                                         +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:30
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                              ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Self as SVec>::Item<'a>> as SVec>::Item,
-   |                                  ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:30
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                              ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Self as SVec>::Item<T>> as SVec>::Item,
-   |                                  +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:46
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                                              ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item<'a>,
-   |                                                  ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:23:46
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item,
-   |                                              ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
-   |                                                  +++
-
-error[E0038]: the trait `SVec` cannot be made into an object
-  --> $DIR/issue-105742.rs:5:31
-   |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-105742.rs:12:17
-   |
-LL |    pub trait SVec: Index<
-   |  ____________----__^
-   | |            |
-   | |            this trait cannot be made into an object...
-LL | |      <Self as SVec>::Item,
-LL | |
-LL | |
-...  |
-LL | |/     Output = <Index<<Self as SVec>::Item,
-LL | ||
-LL | ||
-LL | ||
-LL | ||
-LL | ||     Output = <Self as SVec>::Item> as SVec>::Item,
-   | ||_________________________________________________^ ...because it uses `Self` as a type parameter
-...  |
-LL | |
-LL | |  > {
-   | |__^ ...because it uses `Self` as a type parameter
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:35:38
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item;
-   |                                      ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
-   |                                          ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:35:38
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item;
-   |                                      ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item<T>;
-   |                                          +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:35:38
+  --> $DIR/issue-105742.rs:16:38
    |
 LL |     fn len(&self) -> <Self as SVec>::Item;
    |                                      ^^^^ expected 1 lifetime argument
    |
 note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:33:10
+  --> $DIR/issue-105742.rs:14:10
    |
 LL |     type Item<'a, T>;
    |          ^^^^ --
@@ -364,13 +15,13 @@ LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
    |                                          ++++
 
 error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:35:38
+  --> $DIR/issue-105742.rs:16:38
    |
 LL |     fn len(&self) -> <Self as SVec>::Item;
    |                                      ^^^^ expected 1 generic argument
    |
 note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:33:10
+  --> $DIR/issue-105742.rs:14:10
    |
 LL |     type Item<'a, T>;
    |          ^^^^     -
@@ -379,7 +30,6 @@ help: add missing generic argument
 LL |     fn len(&self) -> <Self as SVec>::Item<T>;
    |                                          +++
 
-error: aborting due to 23 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0038, E0107.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/error-codes/E0520.stderr b/tests/ui/error-codes/E0520.stderr
index 12ecead13de5f..06658a49b83aa 100644
--- a/tests/ui/error-codes/E0520.stderr
+++ b/tests/ui/error-codes/E0520.stderr
@@ -15,7 +15,7 @@ LL | impl<T: Clone> SpaceLlama for T {
    | ------------------------------- parent `impl` is here
 ...
 LL |     default fn fly(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly`
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly`
    |
    = note: to specialize, `fly` in the parent `impl` must be marked `default`
 
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
index 770be2af28146..f9e62a99baee8 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for T {
    | ----------------- parent `impl` is here
 ...
 LL |     fn foo(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `foo`
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
@@ -26,7 +26,7 @@ LL | impl<T> Foo for T {
    | ----------------- parent `impl` is here
 ...
 LL |     fn bar(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `bar`
    |
    = note: to specialize, `bar` in the parent `impl` must be marked `default`
 
@@ -37,7 +37,7 @@ LL | impl<T> Bar for T {
    | ----------------- parent `impl` is here
 ...
 LL |     type T = ();
-   |     ^^^^^^^^^^^^ cannot specialize default item `T`
+   |     ^^^^^^ cannot specialize default item `T`
    |
    = note: to specialize, `T` in the parent `impl` must be marked `default`
 
@@ -48,7 +48,7 @@ LL | impl<T: Clone> Baz for T {
    | ------------------------ parent `impl` is here
 ...
 LL |     fn baz(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `baz`
    |
    = note: to specialize, `baz` in the parent `impl` must be marked `default`
 
@@ -59,7 +59,7 @@ LL | impl<T: Clone> Redundant for T {
    | ------------------------------ parent `impl` is here
 ...
 LL |     fn redundant(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |     ^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr
index 5c136adc451d5..3fc29fff230a3 100644
--- a/tests/ui/specialization/issue-50452-fail.stderr
+++ b/tests/ui/specialization/issue-50452-fail.stderr
@@ -12,7 +12,7 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is n
   --> $DIR/issue-50452-fail.rs:10:5
    |
 LL |     fn foo() {}
-   |     ^^^^^^^^^^^ cannot specialize default item `foo`
+   |     ^^^^^^^^ cannot specialize default item `foo`
 ...
 LL | impl<T> Foo for T {
    | ----------------- parent `impl` is here
diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr
index faa14555a4f39..9d62a353da728 100644
--- a/tests/ui/specialization/non-defaulted-item-fail.stderr
+++ b/tests/ui/specialization/non-defaulted-item-fail.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
 ...
 LL |     type Ty = Vec<()>;
-   |     ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+   |     ^^^^^^^ cannot specialize default item `Ty`
    |
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
@@ -26,7 +26,7 @@ LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
 ...
 LL |     const CONST: u8 = 42;
-   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+   |     ^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
    |
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
@@ -37,7 +37,7 @@ LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
 ...
 LL |     fn foo(&self) -> bool { true }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
@@ -48,7 +48,7 @@ LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
 ...
 LL |     type Ty = Vec<()>;
-   |     ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+   |     ^^^^^^^ cannot specialize default item `Ty`
    |
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
@@ -59,7 +59,7 @@ LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
 ...
 LL |     const CONST: u8 = 42;
-   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+   |     ^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
    |
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
@@ -70,7 +70,7 @@ LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
 ...
 LL |     fn foo(&self) -> bool { true }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr
index 842cec9c79fbb..695a3f6cc45d1 100644
--- a/tests/ui/specialization/specialization-no-default.stderr
+++ b/tests/ui/specialization/specialization-no-default.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for T {
    | ----------------- parent `impl` is here
 ...
 LL |     fn foo(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `foo`
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
@@ -26,7 +26,7 @@ LL | impl<T> Foo for T {
    | ----------------- parent `impl` is here
 ...
 LL |     fn bar(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `bar`
    |
    = note: to specialize, `bar` in the parent `impl` must be marked `default`
 
@@ -37,7 +37,7 @@ LL | impl<T> Bar for T {
    | ----------------- parent `impl` is here
 ...
 LL |     type T = ();
-   |     ^^^^^^^^^^^^ cannot specialize default item `T`
+   |     ^^^^^^ cannot specialize default item `T`
    |
    = note: to specialize, `T` in the parent `impl` must be marked `default`
 
@@ -48,7 +48,7 @@ LL | impl<T: Clone> Baz for T {
    | ------------------------ parent `impl` is here
 ...
 LL |     fn baz(&self) {}
-   |     ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+   |     ^^^^^^^^^^^^^ cannot specialize default item `baz`
    |
    = note: to specialize, `baz` in the parent `impl` must be marked `default`
 
@@ -59,7 +59,7 @@ LL | impl<T: Clone> Redundant for T {
    | ------------------------------ parent `impl` is here
 ...
 LL |     default fn redundant(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr
index 67b94bba12143..040d9d14503f0 100644
--- a/tests/ui/traits/negative-impls/no-items.stderr
+++ b/tests/ui/traits/negative-impls/no-items.stderr
@@ -2,7 +2,7 @@ error[E0749]: negative impls cannot have any items
   --> $DIR/no-items.rs:8:5
    |
 LL |     type Foo = i32;
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 

From 0d39f9d94d2eddd31e4743ae1e3ea269bb3e0984 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 19:46:51 +0000
Subject: [PATCH 5/9] Do not fetch HIR to monomorphize impls.

---
 compiler/rustc_monomorphize/src/collector.rs | 114 +++++++------------
 1 file changed, 42 insertions(+), 72 deletions(-)

diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8f6338472df58..dd7ee220d7311 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1191,28 +1191,14 @@ impl<'v> RootCollector<'_, 'v> {
     fn process_item(&mut self, id: hir::ItemId) {
         match self.tcx.def_kind(id.owner_id) {
             DefKind::Enum | DefKind::Struct | DefKind::Union => {
-                let item = self.tcx.hir().item(id);
-                match item.kind {
-                    hir::ItemKind::Enum(_, ref generics)
-                    | hir::ItemKind::Struct(_, ref generics)
-                    | hir::ItemKind::Union(_, ref generics) => {
-                        if generics.params.is_empty() {
-                            if self.mode == MonoItemCollectionMode::Eager {
-                                debug!(
-                                    "RootCollector: ADT drop-glue for {}",
-                                    self.tcx.def_path_str(item.owner_id.to_def_id())
-                                );
-
-                                let ty = Instance::new(
-                                    item.owner_id.to_def_id(),
-                                    InternalSubsts::empty(),
-                                )
-                                .ty(self.tcx, ty::ParamEnv::reveal_all());
-                                visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
-                            }
-                        }
-                    }
-                    _ => bug!(),
+                if self.tcx.generics_of(id.owner_id).count() == 0
+                    && self.mode == MonoItemCollectionMode::Eager
+                {
+                    debug!("RootCollector: ADT drop-glue for `{id:?}`",);
+
+                    let ty =
+                        self.tcx.bound_type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
+                    visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
                 }
             }
             DefKind::GlobalAsm => {
@@ -1240,8 +1226,7 @@ impl<'v> RootCollector<'_, 'v> {
             }
             DefKind::Impl { .. } => {
                 if self.mode == MonoItemCollectionMode::Eager {
-                    let item = self.tcx.hir().item(id);
-                    create_mono_items_for_default_impls(self.tcx, item, self.output);
+                    create_mono_items_for_default_impls(self.tcx, id, self.output);
                 }
             }
             DefKind::Fn => {
@@ -1326,66 +1311,51 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     generics.requires_monomorphization(tcx)
 }
 
+#[instrument(level = "debug", skip(tcx, output))]
 fn create_mono_items_for_default_impls<'tcx>(
     tcx: TyCtxt<'tcx>,
-    item: &'tcx hir::Item<'tcx>,
+    item: hir::ItemId,
     output: &mut MonoItems<'tcx>,
 ) {
-    match item.kind {
-        hir::ItemKind::Impl(ref impl_) => {
-            if matches!(impl_.polarity, hir::ImplPolarity::Negative(_)) {
-                return;
-            }
+    let polarity = tcx.impl_polarity(item.owner_id);
+    if matches!(polarity, ty::ImplPolarity::Negative) {
+        return;
+    }
 
-            for param in impl_.generics.params {
-                match param.kind {
-                    hir::GenericParamKind::Lifetime { .. } => {}
-                    hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
-                        return;
-                    }
-                }
-            }
+    if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
+        return;
+    }
 
-            debug!(
-                "create_mono_items_for_default_impls(item={})",
-                tcx.def_path_str(item.owner_id.to_def_id())
-            );
+    let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
+        return;
+    };
 
-            if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
-                let trait_ref = trait_ref.subst_identity();
+    let trait_ref = trait_ref.subst_identity();
 
-                let param_env = ty::ParamEnv::reveal_all();
-                let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
-                let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
-                for method in tcx.provided_trait_methods(trait_ref.def_id) {
-                    if overridden_methods.contains_key(&method.def_id) {
-                        continue;
-                    }
+    let param_env = ty::ParamEnv::reveal_all();
+    let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
+    let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
+    for method in tcx.provided_trait_methods(trait_ref.def_id) {
+        if overridden_methods.contains_key(&method.def_id) {
+            continue;
+        }
 
-                    if tcx.generics_of(method.def_id).own_requires_monomorphization() {
-                        continue;
-                    }
+        if tcx.generics_of(method.def_id).own_requires_monomorphization() {
+            continue;
+        }
 
-                    let substs =
-                        InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
-                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                            GenericParamDefKind::Type { .. }
-                            | GenericParamDefKind::Const { .. } => {
-                                trait_ref.substs[param.index as usize]
-                            }
-                        });
-                    let instance =
-                        ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
-
-                    let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
-                    if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
-                    {
-                        output.push(mono_item);
-                    }
-                }
+        let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
+            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+            GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
+                trait_ref.substs[param.index as usize]
             }
+        });
+        let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
+
+        let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
+        if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
+            output.push(mono_item);
         }
-        _ => bug!(),
     }
 }
 

From e49e7f6a2e62670704ec52e10f7639c17afe4f8e Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 20:15:12 +0000
Subject: [PATCH 6/9] Do not fetch HIR to compute symbols.

---
 .../src/back/symbol_export.rs                 | 67 ++++++++++---------
 1 file changed, 34 insertions(+), 33 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 57a99e74c21ad..11bd47a8f0c79 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -2,9 +2,8 @@ use std::collections::hash_map::Entry::*;
 
 use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
@@ -12,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
 use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, SymbolName, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, SymbolName, TyCtxt};
 use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
@@ -74,32 +73,34 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
             //
             // As a result, if this id is an FFI item (foreign item) then we only
             // let it through if it's included statically.
-            match tcx.hir().get_by_def_id(def_id) {
-                Node::ForeignItem(..) => {
-                    tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
-                }
+            if let Some(parent_id) = tcx.opt_local_parent(def_id)
+                && let DefKind::ForeignMod = tcx.def_kind(parent_id)
+            {
+                let library = tcx.native_library(def_id)?;
+                return library.kind.is_statically_included().then_some(def_id);
+            }
 
-                // Only consider nodes that actually have exported symbols.
-                Node::Item(&hir::Item {
-                    kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn(..),
-                    ..
-                })
-                | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
-                    let generics = tcx.generics_of(def_id);
-                    if !generics.requires_monomorphization(tcx)
-                        // Functions marked with #[inline] are codegened with "internal"
-                        // linkage and are not exported unless marked with an extern
-                        // indicator
-                        && (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
-                            || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
-                    {
-                        Some(def_id)
-                    } else {
-                        None
-                    }
-                }
+            // Only consider nodes that actually have exported symbols.
+            match tcx.def_kind(def_id) {
+                DefKind::Fn | DefKind::Static(_) => {}
+                DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {}
+                _ => return None,
+            };
 
-                _ => None,
+            let generics = tcx.generics_of(def_id);
+            if generics.requires_monomorphization(tcx) {
+                return None;
+            }
+
+            // Functions marked with #[inline] are codegened with "internal"
+            // linkage and are not exported unless marked with an extern
+            // indicator
+            if !Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
+                || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator()
+            {
+                Some(def_id)
+            } else {
+                None
             }
         })
         .map(|def_id| {
@@ -118,7 +119,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
                 tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
                 export_level
             );
-            (def_id.to_def_id(), SymbolExportInfo {
+            let info = SymbolExportInfo {
                 level: export_level,
                 kind: if tcx.is_static(def_id.to_def_id()) {
                     if codegen_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
@@ -130,8 +131,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
                     SymbolExportKind::Text
                 },
                 used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
-                    || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) || used,
-            })
+                    || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
+                    || used,
+            };
+            (def_id.to_def_id(), info)
         })
         .collect();
 
@@ -457,9 +460,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
         let target = &tcx.sess.target.llvm_target;
         // WebAssembly cannot export data symbols, so reduce their export level
         if target.contains("emscripten") {
-            if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
-                tcx.hir().get_if_local(sym_def_id)
-            {
+            if let DefKind::Static(_) = tcx.def_kind(sym_def_id) {
                 return SymbolExportLevel::Rust;
             }
         }

From 68fb752035aa954b7881b846ec1cd5bd3354a4cf Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 20:20:45 +0000
Subject: [PATCH 7/9] Do not fetch HIR to check target features.

---
 compiler/rustc_codegen_ssa/src/target_features.rs | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 739963fffd132..a6afbad5b2402 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -3,12 +3,12 @@ use rustc_attr::InstructionSetAttr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
@@ -440,12 +440,9 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxHashSet<Symbol> {
 /// Checks the function annotated with `#[target_feature]` is not a safe
 /// trait method implementation, reporting an error if it is.
 pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
-    let node = tcx.hir().get(hir_id);
-    if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
-        let parent_id = tcx.hir().get_parent_item(hir_id);
-        let parent_item = tcx.hir().expect_item(parent_id.def_id);
-        if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+    if let DefKind::AssocFn = tcx.def_kind(id) {
+        let parent_id = tcx.local_parent(id);
+        if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
             tcx.sess
                 .struct_span_err(
                     attr_span,

From 40cb4d1bc78f9479b6c29ade5d2ecf89dc4eba35 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Sun, 12 Feb 2023 21:08:14 +0000
Subject: [PATCH 8/9] Even less HIR.

---
 .../rustc_hir_analysis/src/check/check.rs     | 18 ++++------
 .../src/check/intrinsicck.rs                  |  4 +--
 .../src/coherence/builtin.rs                  |  3 +-
 .../src/coherence/orphan.rs                   | 36 ++++++++++---------
 4 files changed, 28 insertions(+), 33 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index d5def62885043..71ed9253668cb 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -21,7 +21,9 @@ use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{
+    self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+};
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -174,16 +176,8 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         Ok(l) => l,
         // Foreign statics that overflow their allowed size should emit an error
         Err(LayoutError::SizeOverflow(_))
-            if {
-                let node = tcx.hir().get_by_def_id(def_id);
-                matches!(
-                    node,
-                    hir::Node::ForeignItem(hir::ForeignItem {
-                        kind: hir::ForeignItemKind::Static(..),
-                        ..
-                    })
-                )
-            } =>
+            if matches!(tcx.def_kind(def_id), DefKind::Static(_)
+                if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
         {
             tcx.sess
                 .struct_span_err(span, "extern static is too large for the current architecture")
@@ -215,7 +209,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
     let item = tcx.hir().item(id);
     let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
-        tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
+        tcx.sess.delay_span_bug(item.span, "expected opaque item");
         return;
     };
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 122b6ead8e9d7..56ac18c492792 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -414,7 +414,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                 // Check that sym actually points to a function. Later passes
                 // depend on this.
                 hir::InlineAsmOperand::SymFn { anon_const } => {
-                    let ty = self.tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                    let ty = self.tcx.type_of(anon_const.def_id);
                     match ty.kind() {
                         ty::Never | ty::Error(_) => {}
                         ty::FnDef(..) => {}
@@ -422,7 +422,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                             let mut err =
                                 self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
                             err.span_label(
-                                self.tcx.hir().span(anon_const.body.hir_id),
+                                self.tcx.def_span(anon_const.def_id),
                                 &format!("is {} `{}`", ty.kind().article(), ty),
                             );
                             err.help("`sym` operands must refer to either a function or a static");
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 8c2423e3ca0d1..c0ba385987d77 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -202,8 +202,7 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId)
 fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
 
-    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-    let span = tcx.hir().span(impl_hir_id);
+    let span = tcx.def_span(impl_did);
 
     let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index d0db8cabfddb2..49a9a2ea29309 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -38,26 +38,28 @@ fn do_orphan_check_impl<'tcx>(
     def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_def_id = trait_ref.def_id;
-
-    let item = tcx.hir().expect_item(def_id);
-    let hir::ItemKind::Impl(impl_) = item.kind else {
-        bug!("{:?} is not an impl: {:?}", def_id, item);
-    };
     let sp = tcx.def_span(def_id);
-    let tr = impl_.of_trait.as_ref().unwrap();
 
-    match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
+    match traits::orphan_check(tcx, def_id.to_def_id()) {
         Ok(()) => {}
-        Err(err) => emit_orphan_check_error(
-            tcx,
-            sp,
-            item.span,
-            tr.path.span,
-            trait_ref,
-            impl_.self_ty.span,
-            &impl_.generics,
-            err,
-        )?,
+        Err(err) => {
+            let item = tcx.hir().expect_item(def_id);
+            let hir::ItemKind::Impl(impl_) = item.kind else {
+                bug!("{:?} is not an impl: {:?}", def_id, item);
+            };
+            let tr = impl_.of_trait.as_ref().unwrap();
+
+            emit_orphan_check_error(
+                tcx,
+                sp,
+                item.span,
+                tr.path.span,
+                trait_ref,
+                impl_.self_ty.span,
+                &impl_.generics,
+                err,
+            )?
+        }
     }
 
     // In addition to the above rules, we restrict impls of auto traits

From 065f0b222d4e23ae3d4215061c5df7d248855717 Mon Sep 17 00:00:00 2001
From: Camille GILLOT <gillot.camille@gmail.com>
Date: Tue, 14 Feb 2023 18:12:49 +0000
Subject: [PATCH 9/9] Move query out of path.

---
 compiler/rustc_hir_analysis/src/coherence/orphan.rs | 9 +++++++--
 compiler/rustc_monomorphize/src/collector.rs        | 4 ++--
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 49a9a2ea29309..f0a0e7e3e9293 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -38,7 +38,6 @@ fn do_orphan_check_impl<'tcx>(
     def_id: LocalDefId,
 ) -> Result<(), ErrorGuaranteed> {
     let trait_def_id = trait_ref.def_id;
-    let sp = tcx.def_span(def_id);
 
     match traits::orphan_check(tcx, def_id.to_def_id()) {
         Ok(()) => {}
@@ -48,6 +47,7 @@ fn do_orphan_check_impl<'tcx>(
                 bug!("{:?} is not an impl: {:?}", def_id, item);
             };
             let tr = impl_.of_trait.as_ref().unwrap();
+            let sp = tcx.def_span(def_id);
 
             emit_orphan_check_error(
                 tcx,
@@ -237,7 +237,10 @@ fn do_orphan_check_impl<'tcx>(
             | ty::GeneratorWitnessMIR(..)
             | ty::Bound(..)
             | ty::Placeholder(..)
-            | ty::Infer(..) => span_bug!(sp, "weird self type for autotrait impl"),
+            | ty::Infer(..) => {
+                let sp = tcx.def_span(def_id);
+                span_bug!(sp, "weird self type for autotrait impl")
+            }
 
             ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
         };
@@ -256,6 +259,7 @@ fn do_orphan_check_impl<'tcx>(
                                 is one of the trait object's trait bounds",
                         trait = tcx.def_path_str(trait_def_id),
                     );
+                    let sp = tcx.def_span(def_id);
                     let reported =
                         struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
                     return Err(reported);
@@ -284,6 +288,7 @@ fn do_orphan_check_impl<'tcx>(
                             non-struct/enum type",
                 )),
             } {
+                let sp = tcx.def_span(def_id);
                 let reported =
                     struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
                 return Err(reported);
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index dd7ee220d7311..bbe4e67977c94 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1191,8 +1191,8 @@ impl<'v> RootCollector<'_, 'v> {
     fn process_item(&mut self, id: hir::ItemId) {
         match self.tcx.def_kind(id.owner_id) {
             DefKind::Enum | DefKind::Struct | DefKind::Union => {
-                if self.tcx.generics_of(id.owner_id).count() == 0
-                    && self.mode == MonoItemCollectionMode::Eager
+                if self.mode == MonoItemCollectionMode::Eager
+                    && self.tcx.generics_of(id.owner_id).count() == 0
                 {
                     debug!("RootCollector: ADT drop-glue for `{id:?}`",);