about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-05-07 01:59:11 +0000
committerbors <bors@rust-lang.org>2022-05-07 01:59:11 +0000
commitf6e5570460b2bb925021dc667ead2a9834ea88cb (patch)
tree9e301c7ec30b1d6e89432b3228bb5b303cdc03a6
parent4799baa70d0ff1780ee6dffb743d62c79235ace9 (diff)
parent91ef3ba71d36c17eafd8d582d348d96b8148fbd9 (diff)
downloadrust-f6e5570460b2bb925021dc667ead2a9834ea88cb.tar.gz
rust-f6e5570460b2bb925021dc667ead2a9834ea88cb.zip
Auto merge of #96531 - kckeiks:remove-item-like-visitor-from-rustc-typeck, r=cjgillot
Remove ItemLikeVisitor impls from rustc_typeck

Issue #95004
cc `@cjgillot`
-rw-r--r--compiler/rustc_metadata/src/foreign_modules.rs2
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_passes/src/lang_items.rs4
-rw-r--r--compiler/rustc_typeck/src/check/check.rs81
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs14
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs4
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs149
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs339
-rw-r--r--compiler/rustc_typeck/src/coherence/unsafety.rs150
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check.rs40
-rw-r--r--compiler/rustc_typeck/src/outlives/implicit_infer.rs2
-rw-r--r--compiler/rustc_typeck/src/outlives/test.rs29
-rw-r--r--compiler/rustc_typeck/src/variance/constraints.rs90
-rw-r--r--compiler/rustc_typeck/src/variance/terms.rs86
-rw-r--r--compiler/rustc_typeck/src/variance/test.rs26
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr2
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs12
23 files changed, 504 insertions, 545 deletions
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 97fcbeb4ccc..70da96154b0 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -6,7 +6,7 @@ use rustc_session::cstore::ForeignModule;
 crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
     let mut modules = Vec::new();
     for id in tcx.hir().items() {
-        if !matches!(tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+        if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) {
             continue;
         }
         let item = tcx.hir().item(id);
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 43b6ecee794..f468399930d 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -36,7 +36,7 @@ struct Collector<'tcx> {
 
 impl<'tcx> Collector<'tcx> {
     fn process_item(&mut self, id: rustc_hir::ItemId) {
-        if !matches!(self.tcx.hir().def_kind(id.def_id), DefKind::ForeignMod) {
+        if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) {
             return;
         }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index b2eafa035db..77d6ce1e766 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1813,7 +1813,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             FxHashMap::default();
 
         for id in tcx.hir().items() {
-            if matches!(tcx.hir().def_kind(id.def_id), DefKind::Impl) {
+            if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
                 if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
                     let simplified_self_ty = fast_reject::simplify_type(
                         self.tcx,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 85e53559c29..895cd4f0eac 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -308,11 +308,6 @@ impl<'hir> Map<'hir> {
         Some(def_kind)
     }
 
-    pub fn def_kind(self, local_def_id: LocalDefId) -> DefKind {
-        self.opt_def_kind(local_def_id)
-            .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id))
-    }
-
     pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
         if id.local_id == ItemLocalId::from_u32(0) {
             Some(self.tcx.hir_owner_parent(id.owner))
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 991666908f9..eed90337c0a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2676,7 +2676,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
     // Iterate all local crate items no matter where they are defined.
     let hir = tcx.hir();
     for id in hir.items() {
-        if matches!(hir.def_kind(id.def_id), DefKind::Use) {
+        if matches!(tcx.def_kind(id.def_id), DefKind::Use) {
             continue;
         }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 18f32b04fad..f03d3943f9b 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1164,7 +1164,7 @@ struct RootCollector<'a, 'tcx> {
 
 impl<'v> RootCollector<'_, 'v> {
     fn process_item(&mut self, id: hir::ItemId) {
-        match self.tcx.hir().def_kind(id.def_id) {
+        match self.tcx.def_kind(id.def_id) {
             DefKind::Enum | DefKind::Struct | DefKind::Union => {
                 let item = self.tcx.hir().item(id);
                 match item.kind {
@@ -1225,7 +1225,7 @@ impl<'v> RootCollector<'_, 'v> {
     }
 
     fn process_impl_item(&mut self, id: hir::ImplItemId) {
-        if matches!(self.tcx.hir().def_kind(id.def_id), DefKind::AssocFn) {
+        if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) {
             self.push_if_root(id.def_id);
         }
     }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 18d9bdf8e17..79900a90aed 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -240,9 +240,9 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
     let crate_items = tcx.hir_crate_items(());
 
     for id in crate_items.items() {
-        collector.check_for_lang(Target::from_def_kind(tcx.hir().def_kind(id.def_id)), id.hir_id());
+        collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.def_id)), id.hir_id());
 
-        if matches!(tcx.hir().def_kind(id.def_id), DefKind::Enum) {
+        if matches!(tcx.def_kind(id.def_id), DefKind::Enum) {
             let item = tcx.hir().item(id);
             if let hir::ItemKind::Enum(def, ..) = &item.kind {
                 for variant in def.variants {
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 6a4c0c2091e..4627b58c9bc 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -27,6 +27,7 @@ use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_ty_utils::representability::{self, Representability};
 
+use rustc_hir::def::DefKind;
 use std::iter;
 use std::ops::ControlFlow;
 
@@ -711,28 +712,35 @@ fn check_opaque_meets_bounds<'tcx>(
     });
 }
 
-pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
+pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
-        it.def_id,
-        tcx.def_path_str(it.def_id.to_def_id())
+        id.def_id,
+        tcx.def_path_str(id.def_id.to_def_id())
     );
     let _indenter = indenter();
-    match it.kind {
-        // Consts can play a role in type-checking, so they are included here.
-        hir::ItemKind::Static(..) => {
-            tcx.ensure().typeck(it.def_id);
-            maybe_check_static_with_link_section(tcx, it.def_id, it.span);
-            check_static_inhabited(tcx, it.def_id, it.span);
+    match tcx.def_kind(id.def_id) {
+        DefKind::Static(..) => {
+            tcx.ensure().typeck(id.def_id);
+            maybe_check_static_with_link_section(tcx, id.def_id, tcx.def_span(id.def_id));
+            check_static_inhabited(tcx, id.def_id, tcx.def_span(id.def_id));
         }
-        hir::ItemKind::Const(..) => {
-            tcx.ensure().typeck(it.def_id);
+        DefKind::Const => {
+            tcx.ensure().typeck(id.def_id);
         }
-        hir::ItemKind::Enum(ref enum_definition, _) => {
-            check_enum(tcx, it.span, &enum_definition.variants, it.def_id);
+        DefKind::Enum => {
+            let item = tcx.hir().item(id);
+            let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
+                return;
+            };
+            check_enum(tcx, item.span, &enum_definition.variants, item.def_id);
         }
-        hir::ItemKind::Fn(..) => {} // entirely within check_item_body
-        hir::ItemKind::Impl(ref impl_) => {
+        DefKind::Fn => {} // entirely within check_item_body
+        DefKind::Impl => {
+            let it = tcx.hir().item(id);
+            let hir::ItemKind::Impl(ref impl_) = it.kind else {
+                return;
+            };
             debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id);
             if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) {
                 check_impl_items_against_trait(
@@ -745,7 +753,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                 check_on_unimplemented(tcx, it);
             }
         }
-        hir::ItemKind::Trait(_, _, _, _, ref items) => {
+        DefKind::Trait => {
+            let it = tcx.hir().item(id);
+            let hir::ItemKind::Trait(_, _, _, _, ref items) = it.kind else {
+                return;
+            };
             check_on_unimplemented(tcx, it);
 
             for item in items.iter() {
@@ -771,28 +783,36 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                 }
             }
         }
-        hir::ItemKind::Struct(..) => {
-            check_struct(tcx, it.def_id, it.span);
+        DefKind::Struct => {
+            check_struct(tcx, id.def_id, tcx.def_span(id.def_id));
         }
-        hir::ItemKind::Union(..) => {
-            check_union(tcx, it.def_id, it.span);
+        DefKind::Union => {
+            check_union(tcx, id.def_id, tcx.def_span(id.def_id));
         }
-        hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+        DefKind::OpaqueTy => {
+            let item = tcx.hir().item(id);
+            let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
+                return;
+            };
             // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
             // `async-std` (and `pub async fn` in general).
             // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
             // See https://github.com/rust-lang/rust/issues/75100
             if !tcx.sess.opts.actually_rustdoc {
-                let substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
-                check_opaque(tcx, it.def_id, substs, it.span, &origin);
+                let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
+                check_opaque(tcx, item.def_id, substs, item.span, &origin);
             }
         }
-        hir::ItemKind::TyAlias(..) => {
-            let pty_ty = tcx.type_of(it.def_id);
-            let generics = tcx.generics_of(it.def_id);
+        DefKind::TyAlias => {
+            let pty_ty = tcx.type_of(id.def_id);
+            let generics = tcx.generics_of(id.def_id);
             check_type_params_are_used(tcx, &generics, pty_ty);
         }
-        hir::ItemKind::ForeignMod { abi, items } => {
+        DefKind::ForeignMod => {
+            let it = tcx.hir().item(id);
+            let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
+                return;
+            };
             check_abi(tcx, it.hir_id(), it.span, abi);
 
             if abi == Abi::RustIntrinsic {
@@ -851,7 +871,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
                 }
             }
         }
-        _ => { /* nothing to do */ }
+        _ => {}
     }
 }
 
@@ -1451,7 +1471,10 @@ pub(super) fn check_type_params_are_used<'tcx>(
 }
 
 pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
+    let module = tcx.hir_module_items(module_def_id);
+    for id in module.items() {
+        check_item_type(tcx, id);
+    }
 }
 
 pub(super) use wfcheck::check_item_well_formed;
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 681d1e37f86..ceb862b474a 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -151,7 +151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
                 Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
                     sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                    match def_id.as_local().map(|def_id| hir.def_kind(def_id)) {
+                    match def_id.as_local().map(|def_id| self.tcx.def_kind(def_id)) {
                         Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
                             msg = "instantiate this tuple variant";
                         }
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 76c955d6f69..f88083003a2 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -111,7 +111,6 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
@@ -933,19 +932,6 @@ impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> {
     }
 }
 
-struct CheckItemTypesVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
-    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        check_item_type(self.tcx, i);
-    }
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
-    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
-}
-
 fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
     tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
 }
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index d52886a09bd..1310467aeb9 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -17,7 +17,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     }
 
     for id in tcx.hir().items() {
-        if matches!(tcx.hir().def_kind(id.def_id), DefKind::Use) {
+        if matches!(tcx.def_kind(id.def_id), DefKind::Use) {
             if tcx.visibility(id.def_id).is_public() {
                 continue;
             }
@@ -101,7 +101,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
     let mut crates_to_lint = vec![];
 
     for id in tcx.hir().items() {
-        if matches!(tcx.hir().def_kind(id.def_id), DefKind::ExternCrate) {
+        if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) {
             let item = tcx.hir().item(id);
             if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
                 crates_to_lint.push(ExternCrateToLint {
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index de29a851e2f..b9d4167dbff 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -9,8 +9,8 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
 use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
 use rustc_span::symbol::sym;
@@ -19,7 +19,9 @@ 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 {
     let mut collect = InherentCollect { tcx, impls_map: Default::default() };
-    tcx.hir().visit_all_item_likes(&mut collect);
+    for id in tcx.hir().items() {
+        collect.check_item(id);
+    }
     collect.impls_map
 }
 
@@ -46,79 +48,6 @@ struct InherentCollect<'tcx> {
     impls_map: CrateInherentImpls,
 }
 
-impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, ref items, .. }) = item.kind else {
-            return;
-        };
-
-        let self_ty = self.tcx.type_of(item.def_id);
-        match *self_ty.kind() {
-            ty::Adt(def, _) => {
-                self.check_def_id(item, self_ty, def.did());
-            }
-            ty::Foreign(did) => {
-                self.check_def_id(item, 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());
-            }
-            ty::Dynamic(..) => {
-                struct_span_err!(
-                    self.tcx.sess,
-                    ty.span,
-                    E0785,
-                    "cannot define inherent `impl` for a dyn auto trait"
-                )
-                .span_label(ty.span, "impl requires at least one non-auto trait")
-                .note("define and implement a new trait or type instead")
-                .emit();
-            }
-            ty::Bool
-            | ty::Char
-            | ty::Int(_)
-            | ty::Uint(_)
-            | ty::Float(_)
-            | ty::Str
-            | ty::Array(..)
-            | ty::Slice(_)
-            | ty::RawPtr(_)
-            | ty::Ref(..)
-            | ty::Never
-            | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
-            ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    ty.span,
-                    E0118,
-                    "no nominal type found for inherent implementation"
-                );
-
-                err.span_label(ty.span, "impl requires a nominal type")
-                    .note("either implement a trait on it or create a newtype to wrap it instead");
-
-                err.emit();
-            }
-            ty::FnDef(..)
-            | ty::Closure(..)
-            | ty::Generator(..)
-            | ty::GeneratorWitness(..)
-            | ty::Bound(..)
-            | ty::Placeholder(_)
-            | ty::Infer(_) => {
-                bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
-            }
-            ty::Error(_) => {}
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
-}
-
 const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible";
 const INTO_DEFINING_CRATE: &str =
     "consider moving this inherent impl into the crate defining the type if possible";
@@ -246,4 +175,74 @@ impl<'tcx> InherentCollect<'tcx> {
             bug!("unexpected primitive type: {:?}", ty);
         }
     }
+
+    fn check_item(&mut self, id: hir::ItemId) {
+        if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) {
+            return;
+        }
+
+        let item = self.tcx.hir().item(id);
+        let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, ref items, .. }) = item.kind else {
+            return;
+        };
+
+        let self_ty = self.tcx.type_of(item.def_id);
+        match *self_ty.kind() {
+            ty::Adt(def, _) => {
+                self.check_def_id(item, self_ty, def.did());
+            }
+            ty::Foreign(did) => {
+                self.check_def_id(item, 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());
+            }
+            ty::Dynamic(..) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    ty.span,
+                    E0785,
+                    "cannot define inherent `impl` for a dyn auto trait"
+                )
+                .span_label(ty.span, "impl requires at least one non-auto trait")
+                .note("define and implement a new trait or type instead")
+                .emit();
+            }
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Str
+            | ty::Array(..)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(..)
+            | ty::Never
+            | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
+            ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    ty.span,
+                    E0118,
+                    "no nominal type found for inherent implementation"
+                );
+
+                err.span_label(ty.span, "impl requires a nominal type")
+                    .note("either implement a trait on it or create a newtype to wrap it instead");
+
+                err.emit();
+            }
+            ty::FnDef(..)
+            | ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Bound(..)
+            | ty::Placeholder(_)
+            | ty::Infer(_) => {
+                bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
+            }
+            ty::Error(_) => {}
+        }
+    }
 }
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
index cf71e0f300c..db67c1f7c9e 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_index::vec::IndexVec;
 use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::{self, TyCtxt};
@@ -12,7 +12,10 @@ use smallvec::SmallVec;
 use std::collections::hash_map::Entry;
 
 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) {
-    tcx.hir().visit_all_item_likes(&mut InherentOverlapChecker { tcx });
+    let mut inherent_overlap_checker = InherentOverlapChecker { tcx };
+    for id in tcx.hir().items() {
+        inherent_overlap_checker.check_item(id);
+    }
 }
 
 struct InherentOverlapChecker<'tcx> {
@@ -121,200 +124,184 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
             || true,
         );
     }
-}
 
-impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        match item.kind {
-            hir::ItemKind::Enum(..)
-            | hir::ItemKind::Struct(..)
-            | hir::ItemKind::Trait(..)
-            | hir::ItemKind::Union(..) => {
-                let impls = self.tcx.inherent_impls(item.def_id);
+    fn check_item(&mut self, id: hir::ItemId) {
+        let def_kind = self.tcx.def_kind(id.def_id);
+        if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) {
+            return;
+        }
 
-                // If there is only one inherent impl block,
-                // there is nothing to overlap check it with
-                if impls.len() <= 1 {
-                    return;
-                }
+        let impls = self.tcx.inherent_impls(id.def_id);
 
-                let overlap_mode = OverlapMode::get(self.tcx, item.def_id.to_def_id());
+        // If there is only one inherent impl block,
+        // there is nothing to overlap check it with
+        if impls.len() <= 1 {
+            return;
+        }
 
-                let impls_items = impls
-                    .iter()
-                    .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
-                    .collect::<SmallVec<[_; 8]>>();
+        let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
 
-                // Perform a O(n^2) algorithm for small n,
-                // otherwise switch to an allocating algorithm with
-                // faster asymptotic runtime.
-                const ALLOCATING_ALGO_THRESHOLD: usize = 500;
-                if impls.len() < ALLOCATING_ALGO_THRESHOLD {
-                    for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
-                        for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
-                            if self.impls_have_common_items(impl_items1, impl_items2) {
-                                self.check_for_overlapping_inherent_impls(
-                                    overlap_mode,
-                                    impl1_def_id,
-                                    impl2_def_id,
-                                );
-                            }
-                        }
+        let impls_items = impls
+            .iter()
+            .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
+            .collect::<SmallVec<[_; 8]>>();
+
+        // Perform a O(n^2) algorithm for small n,
+        // otherwise switch to an allocating algorithm with
+        // faster asymptotic runtime.
+        const ALLOCATING_ALGO_THRESHOLD: usize = 500;
+        if impls.len() < ALLOCATING_ALGO_THRESHOLD {
+            for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
+                for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
+                    if self.impls_have_common_items(impl_items1, impl_items2) {
+                        self.check_for_overlapping_inherent_impls(
+                            overlap_mode,
+                            impl1_def_id,
+                            impl2_def_id,
+                        );
                     }
-                } else {
-                    // Build a set of connected regions of impl blocks.
-                    // Two impl blocks are regarded as connected if they share
-                    // an item with the same unhygienic identifier.
-                    // After we have assembled the connected regions,
-                    // run the O(n^2) algorithm on each connected region.
-                    // This is advantageous to running the algorithm over the
-                    // entire graph when there are many connected regions.
+                }
+            }
+        } else {
+            // Build a set of connected regions of impl blocks.
+            // Two impl blocks are regarded as connected if they share
+            // an item with the same unhygienic identifier.
+            // After we have assembled the connected regions,
+            // run the O(n^2) algorithm on each connected region.
+            // This is advantageous to running the algorithm over the
+            // entire graph when there are many connected regions.
 
-                    rustc_index::newtype_index! {
-                        pub struct RegionId {
-                            ENCODABLE = custom
+            rustc_index::newtype_index! {
+                pub struct RegionId {
+                    ENCODABLE = custom
+                }
+            }
+            struct ConnectedRegion {
+                idents: SmallVec<[Symbol; 8]>,
+                impl_blocks: FxHashSet<usize>,
+            }
+            let mut connected_regions: IndexVec<RegionId, _> = Default::default();
+            // Reverse map from the Symbol to the connected region id.
+            let mut connected_region_ids = FxHashMap::default();
+
+            for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() {
+                if impl_items.len() == 0 {
+                    continue;
+                }
+                // First obtain a list of existing connected region ids
+                let mut idents_to_add = SmallVec::<[Symbol; 8]>::new();
+                let mut ids = impl_items
+                    .in_definition_order()
+                    .filter_map(|item| {
+                        let entry = connected_region_ids.entry(item.name);
+                        if let Entry::Occupied(e) = &entry {
+                            Some(*e.get())
+                        } else {
+                            idents_to_add.push(item.name);
+                            None
                         }
+                    })
+                    .collect::<SmallVec<[RegionId; 8]>>();
+                // Sort the id list so that the algorithm is deterministic
+                ids.sort_unstable();
+                ids.dedup();
+                let ids = ids;
+                match &ids[..] {
+                    // Create a new connected region
+                    [] => {
+                        let id_to_set = connected_regions.next_index();
+                        // Update the connected region ids
+                        for ident in &idents_to_add {
+                            connected_region_ids.insert(*ident, id_to_set);
+                        }
+                        connected_regions.insert(
+                            id_to_set,
+                            ConnectedRegion {
+                                idents: idents_to_add,
+                                impl_blocks: std::iter::once(i).collect(),
+                            },
+                        );
                     }
-                    struct ConnectedRegion {
-                        idents: SmallVec<[Symbol; 8]>,
-                        impl_blocks: FxHashSet<usize>,
+                    // Take the only id inside the list
+                    &[id_to_set] => {
+                        let region = connected_regions[id_to_set].as_mut().unwrap();
+                        region.impl_blocks.insert(i);
+                        region.idents.extend_from_slice(&idents_to_add);
+                        // Update the connected region ids
+                        for ident in &idents_to_add {
+                            connected_region_ids.insert(*ident, id_to_set);
+                        }
                     }
-                    let mut connected_regions: IndexVec<RegionId, _> = Default::default();
-                    // Reverse map from the Symbol to the connected region id.
-                    let mut connected_region_ids = FxHashMap::default();
-
-                    for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() {
-                        if impl_items.len() == 0 {
-                            continue;
+                    // We have multiple connected regions to merge.
+                    // In the worst case this might add impl blocks
+                    // one by one and can thus be O(n^2) in the size
+                    // of the resulting final connected region, but
+                    // this is no issue as the final step to check
+                    // for overlaps runs in O(n^2) as well.
+                    &[id_to_set, ..] => {
+                        let mut region = connected_regions.remove(id_to_set).unwrap();
+                        region.impl_blocks.insert(i);
+                        region.idents.extend_from_slice(&idents_to_add);
+                        // Update the connected region ids
+                        for ident in &idents_to_add {
+                            connected_region_ids.insert(*ident, id_to_set);
                         }
-                        // First obtain a list of existing connected region ids
-                        let mut idents_to_add = SmallVec::<[Symbol; 8]>::new();
-                        let mut ids = impl_items
-                            .in_definition_order()
-                            .filter_map(|item| {
-                                let entry = connected_region_ids.entry(item.name);
-                                if let Entry::Occupied(e) = &entry {
-                                    Some(*e.get())
-                                } else {
-                                    idents_to_add.push(item.name);
-                                    None
-                                }
-                            })
-                            .collect::<SmallVec<[RegionId; 8]>>();
-                        // Sort the id list so that the algorithm is deterministic
-                        ids.sort_unstable();
-                        ids.dedup();
-                        let ids = ids;
-                        match &ids[..] {
-                            // Create a new connected region
-                            [] => {
-                                let id_to_set = connected_regions.next_index();
-                                // Update the connected region ids
-                                for ident in &idents_to_add {
-                                    connected_region_ids.insert(*ident, id_to_set);
-                                }
-                                connected_regions.insert(
-                                    id_to_set,
-                                    ConnectedRegion {
-                                        idents: idents_to_add,
-                                        impl_blocks: std::iter::once(i).collect(),
-                                    },
-                                );
-                            }
-                            // Take the only id inside the list
-                            &[id_to_set] => {
-                                let region = connected_regions[id_to_set].as_mut().unwrap();
-                                region.impl_blocks.insert(i);
-                                region.idents.extend_from_slice(&idents_to_add);
-                                // Update the connected region ids
-                                for ident in &idents_to_add {
-                                    connected_region_ids.insert(*ident, id_to_set);
-                                }
-                            }
-                            // We have multiple connected regions to merge.
-                            // In the worst case this might add impl blocks
-                            // one by one and can thus be O(n^2) in the size
-                            // of the resulting final connected region, but
-                            // this is no issue as the final step to check
-                            // for overlaps runs in O(n^2) as well.
-                            &[id_to_set, ..] => {
-                                let mut region = connected_regions.remove(id_to_set).unwrap();
-                                region.impl_blocks.insert(i);
-                                region.idents.extend_from_slice(&idents_to_add);
-                                // Update the connected region ids
-                                for ident in &idents_to_add {
-                                    connected_region_ids.insert(*ident, id_to_set);
-                                }
-
-                                // Remove other regions from ids.
-                                for &id in ids.iter() {
-                                    if id == id_to_set {
-                                        continue;
-                                    }
-                                    let r = connected_regions.remove(id).unwrap();
-                                    for ident in r.idents.iter() {
-                                        connected_region_ids.insert(*ident, id_to_set);
-                                    }
-                                    region.idents.extend_from_slice(&r.idents);
-                                    region.impl_blocks.extend(r.impl_blocks);
-                                }
 
-                                connected_regions.insert(id_to_set, region);
+                        // Remove other regions from ids.
+                        for &id in ids.iter() {
+                            if id == id_to_set {
+                                continue;
+                            }
+                            let r = connected_regions.remove(id).unwrap();
+                            for ident in r.idents.iter() {
+                                connected_region_ids.insert(*ident, id_to_set);
                             }
+                            region.idents.extend_from_slice(&r.idents);
+                            region.impl_blocks.extend(r.impl_blocks);
                         }
+
+                        connected_regions.insert(id_to_set, region);
                     }
+                }
+            }
 
-                    debug!(
-                        "churning through {} components (sum={}, avg={}, var={}, max={})",
-                        connected_regions.len(),
-                        impls.len(),
-                        impls.len() / connected_regions.len(),
-                        {
-                            let avg = impls.len() / connected_regions.len();
-                            let s = connected_regions
-                                .iter()
-                                .flatten()
-                                .map(|r| r.impl_blocks.len() as isize - avg as isize)
-                                .map(|v| v.abs() as usize)
-                                .sum::<usize>();
-                            s / connected_regions.len()
-                        },
-                        connected_regions
-                            .iter()
-                            .flatten()
-                            .map(|r| r.impl_blocks.len())
-                            .max()
-                            .unwrap()
-                    );
-                    // List of connected regions is built. Now, run the overlap check
-                    // for each pair of impl blocks in the same connected region.
-                    for region in connected_regions.into_iter().flatten() {
-                        let mut impl_blocks =
-                            region.impl_blocks.into_iter().collect::<SmallVec<[usize; 8]>>();
-                        impl_blocks.sort_unstable();
-                        for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
-                            let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
-                            for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
-                                let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
-                                if self.impls_have_common_items(impl_items1, impl_items2) {
-                                    self.check_for_overlapping_inherent_impls(
-                                        overlap_mode,
-                                        impl1_def_id,
-                                        impl2_def_id,
-                                    );
-                                }
-                            }
+            debug!(
+                "churning through {} components (sum={}, avg={}, var={}, max={})",
+                connected_regions.len(),
+                impls.len(),
+                impls.len() / connected_regions.len(),
+                {
+                    let avg = impls.len() / connected_regions.len();
+                    let s = connected_regions
+                        .iter()
+                        .flatten()
+                        .map(|r| r.impl_blocks.len() as isize - avg as isize)
+                        .map(|v| v.abs() as usize)
+                        .sum::<usize>();
+                    s / connected_regions.len()
+                },
+                connected_regions.iter().flatten().map(|r| r.impl_blocks.len()).max().unwrap()
+            );
+            // List of connected regions is built. Now, run the overlap check
+            // for each pair of impl blocks in the same connected region.
+            for region in connected_regions.into_iter().flatten() {
+                let mut impl_blocks =
+                    region.impl_blocks.into_iter().collect::<SmallVec<[usize; 8]>>();
+                impl_blocks.sort_unstable();
+                for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
+                    let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
+                    for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
+                        let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
+                        if self.impls_have_common_items(impl_items1, impl_items2) {
+                            self.check_for_overlapping_inherent_impls(
+                                overlap_mode,
+                                impl1_def_id,
+                                impl2_def_id,
+                            );
                         }
                     }
                 }
             }
-            _ => {}
         }
     }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index f7aabf2406f..3cfc96ccbfd 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -3,101 +3,83 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
 
 pub fn check(tcx: TyCtxt<'_>) {
-    let mut unsafety = UnsafetyChecker { tcx };
-    tcx.hir().visit_all_item_likes(&mut unsafety);
+    for id in tcx.hir().items() {
+        if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
+            let item = tcx.hir().item(id);
+            if let hir::ItemKind::Impl(ref impl_) = item.kind {
+                check_unsafety_coherence(
+                    tcx,
+                    item,
+                    Some(&impl_.generics),
+                    impl_.unsafety,
+                    impl_.polarity,
+                );
+            }
+        }
+    }
 }
 
-struct UnsafetyChecker<'tcx> {
+fn check_unsafety_coherence<'tcx>(
     tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> UnsafetyChecker<'tcx> {
-    fn check_unsafety_coherence(
-        &mut self,
-        item: &hir::Item<'_>,
-        impl_generics: Option<&hir::Generics<'_>>,
-        unsafety: hir::Unsafety,
-        polarity: hir::ImplPolarity,
-    ) {
-        if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id) {
-            let trait_def = self.tcx.trait_def(trait_ref.def_id);
-            let unsafe_attr = impl_generics.and_then(|generics| {
-                generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
-            });
-            match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
-                (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0199,
-                        "implementing the trait `{}` is not unsafe",
-                        trait_ref.print_only_trait_path()
-                    )
-                    .emit();
-                }
-
-                (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0200,
-                        "the trait `{}` requires an `unsafe impl` declaration",
-                        trait_ref.print_only_trait_path()
-                    )
-                    .emit();
-                }
+    item: &hir::Item<'_>,
+    impl_generics: Option<&hir::Generics<'_>>,
+    unsafety: hir::Unsafety,
+    polarity: hir::ImplPolarity,
+) {
+    if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
+        let trait_def = tcx.trait_def(trait_ref.def_id);
+        let unsafe_attr = impl_generics.and_then(|generics| {
+            generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
+        });
+        match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
+            (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0199,
+                    "implementing the trait `{}` is not unsafe",
+                    trait_ref.print_only_trait_path()
+                )
+                .emit();
+            }
 
-                (
-                    Unsafety::Normal,
-                    Some(attr_name),
-                    Unsafety::Normal,
-                    hir::ImplPolarity::Positive,
-                ) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0569,
-                        "requires an `unsafe impl` declaration due to `#[{}]` attribute",
-                        attr_name
-                    )
-                    .emit();
-                }
+            (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0200,
+                    "the trait `{}` requires an `unsafe impl` declaration",
+                    trait_ref.print_only_trait_path()
+                )
+                .emit();
+            }
 
-                (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
-                    // Reported in AST validation
-                    self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
-                }
-                (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
-                | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
-                | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
-                | (Unsafety::Normal, None, Unsafety::Normal, _) => {
-                    // OK
-                }
+            (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
+                struct_span_err!(
+                    tcx.sess,
+                    item.span,
+                    E0569,
+                    "requires an `unsafe impl` declaration due to `#[{}]` attribute",
+                    attr_name
+                )
+                .emit();
             }
-        }
-    }
-}
 
-impl<'tcx> ItemLikeVisitor<'_> for UnsafetyChecker<'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if let hir::ItemKind::Impl(ref impl_) = item.kind {
-            self.check_unsafety_coherence(
-                item,
-                Some(&impl_.generics),
-                impl_.unsafety,
-                impl_.polarity,
-            );
+            (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => {
+                // Reported in AST validation
+                tcx.sess.delay_span_bug(item.span, "unsafe negative impl");
+            }
+            (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_))
+            | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive)
+            | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive)
+            | (Unsafety::Normal, None, Unsafety::Normal, _) => {
+                // OK
+            }
         }
     }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
 }
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index 8b376e26dee..c089d25d222 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -14,8 +14,8 @@ use min_specialization::check_min_specialization;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::Span;
@@ -63,35 +63,23 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
 
 fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     let min_specialization = tcx.features().min_specialization;
-    tcx.hir()
-        .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization });
-}
-
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_impl_wf, ..*providers };
-}
-
-struct ImplWfCheck<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    min_specialization: bool,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let hir::ItemKind::Impl(ref impl_) = item.kind {
-            enforce_impl_params_are_constrained(self.tcx, item.def_id, impl_.items);
-            enforce_impl_items_are_distinct(self.tcx, impl_.items);
-            if self.min_specialization {
-                check_min_specialization(self.tcx, item.def_id.to_def_id(), item.span);
+    let module = tcx.hir_module_items(module_def_id);
+    for id in module.items() {
+        if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
+            let item = tcx.hir().item(id);
+            if let hir::ItemKind::Impl(ref impl_) = item.kind {
+                enforce_impl_params_are_constrained(tcx, item.def_id, impl_.items);
+                enforce_impl_items_are_distinct(tcx, impl_.items);
+                if min_specialization {
+                    check_min_specialization(tcx, item.def_id.to_def_id(), item.span);
+                }
             }
         }
     }
+}
 
-    fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem<'tcx>) {}
-
-    fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem<'tcx>) {}
-
-    fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { check_mod_impl_wf, ..*providers };
 }
 
 fn enforce_impl_params_are_constrained(
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 6f842c6e71a..96dc83b259f 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -35,7 +35,7 @@ pub fn infer_predicates<'tcx>(
             debug!("InferVisitor::visit_item(item={:?})", item_did);
 
             let mut item_required_predicates = RequiredPredicates::default();
-            match tcx.hir().def_kind(item_did) {
+            match tcx.def_kind(item_did) {
                 DefKind::Union | DefKind::Enum | DefKind::Struct => {
                     let adt_def = tcx.adt_def(item_did.to_def_id());
 
diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs
index b3efd9f9ec3..eb0e1203405 100644
--- a/compiler/rustc_typeck/src/outlives/test.rs
+++ b/compiler/rustc_typeck/src/outlives/test.rs
@@ -1,28 +1,21 @@
 use rustc_errors::struct_span_err;
-use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
 pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
-    tcx.hir().visit_all_item_likes(&mut OutlivesTest { tcx });
-}
-
-struct OutlivesTest<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
+    for id in tcx.hir().items() {
         // For unit testing: check for a special "rustc_outlives"
         // attribute and report an error with various results if found.
-        if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_outlives) {
-            let inferred_outlives_of = self.tcx.inferred_outlives_of(item.def_id);
-            struct_span_err!(self.tcx.sess, item.span, E0640, "{:?}", inferred_outlives_of).emit();
+        if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) {
+            let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id);
+            struct_span_err!(
+                tcx.sess,
+                tcx.def_span(id.def_id),
+                E0640,
+                "{:?}",
+                inferred_outlives_of
+            )
+            .emit();
         }
     }
-
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
-    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index 76755de4964..be8e825d990 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -5,7 +5,7 @@
 
 use hir::def_id::{DefId, LocalDefId};
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -62,61 +62,71 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
         constraints: Vec::new(),
     };
 
-    tcx.hir().visit_all_item_likes(&mut constraint_cx);
+    let crate_items = tcx.hir_crate_items(());
+
+    for id in crate_items.items() {
+        constraint_cx.check_item(id);
+    }
+
+    for id in crate_items.trait_items() {
+        if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
+            constraint_cx.check_node_helper(id.hir_id());
+        }
+    }
+
+    for id in crate_items.impl_items() {
+        if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
+            constraint_cx.check_node_helper(id.hir_id());
+        }
+    }
+
+    for id in crate_items.foreign_items() {
+        if let DefKind::Fn = tcx.def_kind(id.def_id) {
+            constraint_cx.check_node_helper(id.hir_id());
+        }
+    }
 
     constraint_cx
 }
 
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        match item.kind {
-            hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                self.visit_node_helper(item.hir_id());
-
-                if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.visit_node_helper(struct_def.ctor_hir_id().unwrap());
+impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
+    fn check_item(&mut self, id: hir::ItemId) {
+        let def_kind = self.tcx().def_kind(id.def_id);
+        match def_kind {
+            DefKind::Struct | DefKind::Union => {
+                let item = self.tcx().hir().item(id);
+
+                if let hir::ItemKind::Struct(ref struct_def, _)
+                | hir::ItemKind::Union(ref struct_def, _) = item.kind
+                {
+                    self.check_node_helper(item.hir_id());
+
+                    if let hir::VariantData::Tuple(..) = *struct_def {
+                        self.check_node_helper(struct_def.ctor_hir_id().unwrap());
+                    }
                 }
             }
+            DefKind::Enum => {
+                let item = self.tcx().hir().item(id);
 
-            hir::ItemKind::Enum(ref enum_def, _) => {
-                self.visit_node_helper(item.hir_id());
+                if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
+                    self.check_node_helper(item.hir_id());
 
-                for variant in enum_def.variants {
-                    if let hir::VariantData::Tuple(..) = variant.data {
-                        self.visit_node_helper(variant.data.ctor_hir_id().unwrap());
+                    for variant in enum_def.variants {
+                        if let hir::VariantData::Tuple(..) = variant.data {
+                            self.check_node_helper(variant.data.ctor_hir_id().unwrap());
+                        }
                     }
                 }
             }
-
-            hir::ItemKind::Fn(..) => {
-                self.visit_node_helper(item.hir_id());
+            DefKind::Fn => {
+                self.check_node_helper(id.hir_id());
             }
-
             _ => {}
         }
     }
 
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
-            self.visit_node_helper(trait_item.hir_id());
-        }
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
-            self.visit_node_helper(impl_item.hir_id());
-        }
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
-        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-            self.visit_node_helper(foreign_item.hir_id());
-        }
-    }
-}
-
-impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
-    fn visit_node_helper(&mut self, id: hir::HirId) {
+    fn check_node_helper(&mut self, id: hir::HirId) {
         let tcx = self.terms_cx.tcx;
         let def_id = tcx.hir().local_def_id(id);
         self.build_constraints_for_item(def_id);
diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_typeck/src/variance/terms.rs
index 36fbfc21ff5..ab64befe5dc 100644
--- a/compiler/rustc_typeck/src/variance/terms.rs
+++ b/compiler/rustc_typeck/src/variance/terms.rs
@@ -11,7 +11,7 @@
 
 use rustc_arena::DroplessArena;
 use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
+use rustc_hir::def::DefKind;
 use rustc_hir::HirIdMap;
 use rustc_middle::ty::{self, TyCtxt};
 use std::fmt;
@@ -79,7 +79,29 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
     //
     // - https://rustc-dev-guide.rust-lang.org/query.html
     // - https://rustc-dev-guide.rust-lang.org/variance.html
-    tcx.hir().visit_all_item_likes(&mut terms_cx);
+    let crate_items = tcx.hir_crate_items(());
+
+    for id in crate_items.items() {
+        terms_cx.check_item(id);
+    }
+
+    for id in crate_items.trait_items() {
+        if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
+            terms_cx.add_inferreds_for_item(id.hir_id());
+        }
+    }
+
+    for id in crate_items.impl_items() {
+        if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
+            terms_cx.add_inferreds_for_item(id.hir_id());
+        }
+    }
+
+    for id in crate_items.foreign_items() {
+        if let DefKind::Fn = tcx.def_kind(id.def_id) {
+            terms_cx.add_inferreds_for_item(id.hir_id());
+        }
+    }
 
     terms_cx
 }
@@ -124,54 +146,42 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
             (start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))),
         );
     }
-}
 
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item<'_>) {
-        debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(item.hir_id()));
+    fn check_item(&mut self, id: hir::ItemId) {
+        debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(id.hir_id()));
+
+        let def_kind = self.tcx.def_kind(id.def_id);
+        match def_kind {
+            DefKind::Struct | DefKind::Union => {
+                let item = self.tcx.hir().item(id);
 
-        match item.kind {
-            hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
-                self.add_inferreds_for_item(item.hir_id());
+                if let hir::ItemKind::Struct(ref struct_def, _)
+                | hir::ItemKind::Union(ref struct_def, _) = item.kind
+                {
+                    self.add_inferreds_for_item(item.hir_id());
 
-                if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
+                    if let hir::VariantData::Tuple(..) = *struct_def {
+                        self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
+                    }
                 }
             }
+            DefKind::Enum => {
+                let item = self.tcx.hir().item(id);
 
-            hir::ItemKind::Enum(ref enum_def, _) => {
-                self.add_inferreds_for_item(item.hir_id());
+                if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
+                    self.add_inferreds_for_item(item.hir_id());
 
-                for variant in enum_def.variants {
-                    if let hir::VariantData::Tuple(..) = variant.data {
-                        self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap());
+                    for variant in enum_def.variants {
+                        if let hir::VariantData::Tuple(..) = variant.data {
+                            self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap());
+                        }
                     }
                 }
             }
-
-            hir::ItemKind::Fn(..) => {
-                self.add_inferreds_for_item(item.hir_id());
+            DefKind::Fn => {
+                self.add_inferreds_for_item(id.hir_id());
             }
-
             _ => {}
         }
     }
-
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) {
-        if let hir::TraitItemKind::Fn(..) = trait_item.kind {
-            self.add_inferreds_for_item(trait_item.hir_id());
-        }
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) {
-        if let hir::ImplItemKind::Fn(..) = impl_item.kind {
-            self.add_inferreds_for_item(impl_item.hir_id());
-        }
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem<'_>) {
-        if let hir::ForeignItemKind::Fn(..) = foreign_item.kind {
-            self.add_inferreds_for_item(foreign_item.hir_id());
-        }
-    }
 }
diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs
index d6959075d88..2ba87db880b 100644
--- a/compiler/rustc_typeck/src/variance/test.rs
+++ b/compiler/rustc_typeck/src/variance/test.rs
@@ -1,28 +1,14 @@
 use rustc_errors::struct_span_err;
-use rustc_hir as hir;
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
 pub fn test_variance(tcx: TyCtxt<'_>) {
-    tcx.hir().visit_all_item_likes(&mut VarianceTest { tcx });
-}
-
-struct VarianceTest<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        // For unit testing: check for a special "rustc_variance"
-        // attribute and report an error with various results if found.
-        if self.tcx.has_attr(item.def_id.to_def_id(), sym::rustc_variance) {
-            let variances_of = self.tcx.variances_of(item.def_id);
-            struct_span_err!(self.tcx.sess, item.span, E0208, "{:?}", variances_of).emit();
+    // For unit testing: check for a special "rustc_variance"
+    // attribute and report an error with various results if found.
+    for id in tcx.hir().items() {
+        if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) {
+            let variances_of = tcx.variances_of(id.def_id);
+            struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit();
         }
     }
-
-    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem<'tcx>) {}
-    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem<'tcx>) {}
-    fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {}
 }
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
index 0331e75b2fe..590475fa03a 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.rs
@@ -29,7 +29,7 @@ mod x {
 mod y {
     use {Foo, Bar};
 
-    #[rustc_then_this_would_need(typeck)] //~ ERROR no path
+    #[rustc_then_this_would_need(typeck)] //~ ERROR OK
     pub fn call_bar() {
         char::bar('a');
     }
diff --git a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
index 08f382cc024..4e10437362c 100644
--- a/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
+++ b/src/test/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr
@@ -1,4 +1,4 @@
-error: no path from `x::<impl Foo for char>` to `typeck`
+error: OK
   --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5
    |
 LL |     #[rustc_then_this_would_need(typeck)]
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 f63925a2f14..c5c174cc8f6 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -51,14 +51,14 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
         let mut map = FxHashMap::<Res, ExistingName>::default();
 
         for id in cx.tcx.hir().items() {
-            if matches!(cx.tcx.hir().def_kind(id.def_id), DefKind::Impl)
+            if matches!(cx.tcx.def_kind(id.def_id), DefKind::Impl)
                 && let item = cx.tcx.hir().item(id)
                 && let ItemKind::Impl(Impl {
-                    items,
-                    of_trait,
-                    self_ty,
-                    ..
-                }) = &item.kind
+                  items,
+                  of_trait,
+                  self_ty,
+                  ..
+                                      }) = &item.kind
                 && let TyKind::Path(QPath::Resolved(_, Path { res, .. })) = self_ty.kind
             {
                 if !map.contains_key(res) {