about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-06-28 03:44:33 +0000
committerbors <bors@rust-lang.org>2022-06-28 03:44:33 +0000
commit5ffa8f67b75be56cf829bfc9d055082c8382c0cf (patch)
tree0a7f21e49805665acb11aea64c29382e92356897 /compiler
parent7f08d04d60d03e1a52dae61ce6aa50996898702b (diff)
parentf446bbce728d3fb7ec006b72b4eb7cf72160846a (diff)
downloadrust-5ffa8f67b75be56cf829bfc9d055082c8382c0cf.tar.gz
rust-5ffa8f67b75be56cf829bfc9d055082c8382c0cf.zip
Auto merge of #98222 - cjgillot:single-wf, r=michaelwoerister
Only keep a single query for well-formed checking

There are currently 3 queries to perform wf checks on different item-likes.  This complexity is not required.

This PR replaces the query by:
- one query per item;
- one query to invoke it for a whole module.

This allows to remove HIR `ParItemLikeVisitor`.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir/src/intravisit.rs24
-rw-r--r--compiler/rustc_hir/src/itemlikevisit.rs9
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs21
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs17
-rw-r--r--compiler/rustc_middle/src/query/mod.rs12
-rw-r--r--compiler/rustc_typeck/src/check/check.rs13
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs10
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs147
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check.rs7
-rw-r--r--compiler/rustc_typeck/src/lib.rs8
11 files changed, 92 insertions, 177 deletions
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index e68274e2ad9..384a0f9c225 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -65,7 +65,6 @@
 //! example generator inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use crate::itemlikevisit::ParItemLikeVisitor;
 use rustc_ast::walk_list;
 use rustc_ast::{Attribute, Label};
 use rustc_span::symbol::{Ident, Symbol};
@@ -76,29 +75,6 @@ pub trait IntoVisitor<'hir> {
     fn into_visitor(&self) -> Self::Visitor;
 }
 
-pub struct ParDeepVisitor<V>(pub V);
-
-impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
-where
-    V: IntoVisitor<'hir>,
-{
-    fn visit_item(&self, item: &'hir Item<'hir>) {
-        self.0.into_visitor().visit_item(item);
-    }
-
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) {
-        self.0.into_visitor().visit_trait_item(trait_item);
-    }
-
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
-        self.0.into_visitor().visit_impl_item(impl_item);
-    }
-
-    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>) {
-        self.0.into_visitor().visit_foreign_item(foreign_item);
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// `#[xxx] pub async/const/extern "Abi" fn foo()`
diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs
deleted file mode 100644
index a490268dc9f..00000000000
--- a/compiler/rustc_hir/src/itemlikevisit.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use super::{ForeignItem, ImplItem, Item, TraitItem};
-
-/// A parallel variant of `ItemLikeVisitor`.
-pub trait ParItemLikeVisitor<'hir> {
-    fn visit_item(&self, item: &'hir Item<'hir>);
-    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
-    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
-    fn visit_foreign_item(&self, foreign_item: &'hir ForeignItem<'hir>);
-}
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index d845c433d8c..9f32a7da159 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -27,7 +27,6 @@ pub use rustc_span::def_id;
 mod hir;
 pub mod hir_id;
 pub mod intravisit;
-pub mod itemlikevisit;
 pub mod lang_items;
 pub mod pat_util;
 mod stable_hash_impls;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 738d47ba296..a27b8470e95 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -612,23 +612,6 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    /// A parallel version of `visit_all_item_likes`.
-    pub fn par_visit_all_item_likes<V>(self, visitor: &V)
-    where
-        V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
-    {
-        let krate = self.krate();
-        par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) {
-            MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item),
-            MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
-            MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
-            MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
-            MaybeOwner::Owner(OwnerNode::Crate(_))
-            | MaybeOwner::NonOwner(_)
-            | MaybeOwner::Phantom => {}
-        })
-    }
-
     /// If you don't care about nesting, you should use the
     /// `tcx.hir_module_items()` query or `module_items()` instead.
     /// Please see notes in `deep_visit_all_item_likes`.
@@ -867,6 +850,10 @@ impl<'hir> Map<'hir> {
         )
     }
 
+    pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> {
+        self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node
+    }
+
     pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
         match self.tcx.hir_owner(id) {
             Some(Owner { node: OwnerNode::Item(item), .. }) => item,
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 09b142e0c41..8622a620721 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -10,6 +10,7 @@ use crate::ty::query::Providers;
 use crate::ty::{DefIdTree, ImplSubject, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
@@ -61,6 +62,22 @@ impl ModuleItems {
     pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> + '_ {
         self.foreign_items.iter().copied()
     }
+
+    pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
+        par_for_each_in(&self.items[..], |&id| f(id))
+    }
+
+    pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + Send + Sync) {
+        par_for_each_in(&self.trait_items[..], |&id| f(id))
+    }
+
+    pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + Send + Sync) {
+        par_for_each_in(&self.impl_items[..], |&id| f(id))
+    }
+
+    pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + Send + Sync) {
+        par_for_each_in(&self.foreign_items[..], |&id| f(id))
+    }
 }
 
 impl<'tcx> TyCtxt<'tcx> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6c3894bbcf7..2e68fc8a7c0 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -826,6 +826,10 @@ rustc_queries! {
         desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
     }
 
+    query check_mod_type_wf(key: LocalDefId) -> () {
+        desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
+    }
+
     query collect_mod_item_types(key: LocalDefId) -> () {
         desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) }
     }
@@ -1399,13 +1403,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query check_item_well_formed(key: LocalDefId) -> () {
-        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
-    }
-    query check_trait_item_well_formed(key: LocalDefId) -> () {
-        desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
-    }
-    query check_impl_item_well_formed(key: LocalDefId) -> () {
+    query check_well_formed(key: LocalDefId) -> () {
         desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
     }
 
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 45c011b78e3..8ffffbed93c 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -32,11 +32,6 @@ use rustc_ty_utils::representability::{self, Representability};
 use std::iter;
 use std::ops::ControlFlow;
 
-pub fn check_wf_new(tcx: TyCtxt<'_>) {
-    let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
-    tcx.hir().par_visit_all_item_likes(&visit);
-}
-
 pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
     match tcx.sess.target.is_abi_supported(abi) {
         Some(true) => (),
@@ -754,7 +749,7 @@ fn check_opaque_meets_bounds<'tcx>(
     });
 }
 
-pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
+fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
     debug!(
         "check_item_type(it.def_id={:?}, it.name={})",
         id.def_id,
@@ -1543,12 +1538,6 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     }
 }
 
-pub(super) use wfcheck::check_item_well_formed;
-
-pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed;
-
-pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed;
-
 fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
     struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
         .span_label(span, "recursive `async fn`")
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index e26f211c1c1..0ede9ef7756 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -93,11 +93,7 @@ mod upvar;
 mod wfcheck;
 pub mod writeback;
 
-use check::{
-    check_abi, check_fn, check_impl_item_well_formed, check_item_well_formed, check_mod_item_types,
-    check_trait_item_well_formed,
-};
-pub use check::{check_item_type, check_wf_new};
+use check::{check_abi, check_fn, check_mod_item_types};
 pub use diverges::Diverges;
 pub use expectation::Expectation;
 pub use fn_ctxt::*;
@@ -245,6 +241,7 @@ impl<'tcx> EnclosingBreakables<'tcx> {
 
 pub fn provide(providers: &mut Providers) {
     method::provide(providers);
+    wfcheck::provide(providers);
     *providers = Providers {
         typeck_item_bodies,
         typeck_const_arg,
@@ -253,9 +250,6 @@ pub fn provide(providers: &mut Providers) {
         has_typeck_results,
         adt_destructor,
         used_trait_imports,
-        check_item_well_formed,
-        check_trait_item_well_formed,
-        check_impl_item_well_formed,
         check_mod_item_types,
         region_scope_tree,
         ..*providers
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 40344b2ed60..67eb88b73fd 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -7,21 +7,18 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit as hir_visit;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::region_constraints::GenericKind;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
-    self, AdtKind, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeVisitor,
+    self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt,
+    TypeFoldable, TypeSuperFoldable, TypeVisitor,
 };
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -70,6 +67,23 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
     }
 }
 
+fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    let node = tcx.hir().expect_owner(def_id);
+    match node {
+        hir::OwnerNode::Crate(_) => {}
+        hir::OwnerNode::Item(item) => check_item(tcx, item),
+        hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
+        hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
+        hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
+    }
+
+    if let Some(generics) = node.generics() {
+        for param in generics.params {
+            check_param_wf(tcx, param)
+        }
+    }
+}
+
 /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
 /// well-formed, meaning that they do not require any constraints not declared in the struct
 /// definition itself. For example, this definition would be illegal:
@@ -84,8 +98,8 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
 #[instrument(skip(tcx), level = "debug")]
-pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let item = tcx.hir().expect_item(def_id);
+fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
+    let def_id = item.def_id;
 
     debug!(
         ?item.def_id,
@@ -156,20 +170,6 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::Const(ty, ..) => {
             check_item_type(tcx, item.def_id, ty.span, false);
         }
-        hir::ItemKind::ForeignMod { items, .. } => {
-            for it in items.iter() {
-                let it = tcx.hir().foreign_item(it.id);
-                match it.kind {
-                    hir::ForeignItemKind::Fn(decl, ..) => {
-                        check_item_fn(tcx, it.def_id, it.ident, it.span, decl)
-                    }
-                    hir::ForeignItemKind::Static(ty, ..) => {
-                        check_item_type(tcx, it.def_id, ty.span, true)
-                    }
-                    hir::ForeignItemKind::Type => (),
-                }
-            }
-        }
         hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
             check_type_defn(tcx, item, false, |fcx| vec![fcx.non_enum_variant(struct_def)]);
 
@@ -191,13 +191,31 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         hir::ItemKind::TraitAlias(..) => {
             check_trait(tcx, item);
         }
+        // `ForeignItem`s are handled separately.
+        hir::ItemKind::ForeignMod { .. } => {}
         _ => {}
     }
 }
 
-pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let trait_item = tcx.hir().expect_trait_item(def_id);
+fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
+    let def_id = item.def_id;
+
+    debug!(
+        ?item.def_id,
+        item.name = ? tcx.def_path_str(def_id.to_def_id())
+    );
+
+    match item.kind {
+        hir::ForeignItemKind::Fn(decl, ..) => {
+            check_item_fn(tcx, item.def_id, item.ident, item.span, decl)
+        }
+        hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true),
+        hir::ForeignItemKind::Type => (),
+    }
+}
+
+fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
+    let def_id = trait_item.def_id;
 
     let (method_sig, span) = match trait_item.kind {
         hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -207,7 +225,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     check_object_unsafe_self_trait_by_name(tcx, trait_item);
     check_associated_item(tcx, trait_item.def_id, span, method_sig);
 
-    let encl_trait_def_id = tcx.hir().get_parent_item(hir_id);
+    let encl_trait_def_id = tcx.local_parent(def_id);
     let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
     let encl_trait_def_id = encl_trait.def_id.to_def_id();
     let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
@@ -764,8 +782,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
     }
 }
 
-pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let impl_item = tcx.hir().expect_impl_item(def_id);
+fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
+    let def_id = impl_item.def_id;
 
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
@@ -774,7 +792,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         _ => (None, impl_item.span),
     };
 
-    check_associated_item(tcx, impl_item.def_id, span, method_sig);
+    check_associated_item(tcx, def_id, span, method_sig);
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -1822,67 +1840,12 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirI
     fcx.select_all_obligations_or_error();
 }
 
-#[derive(Clone, Copy)]
-pub struct CheckTypeWellFormedVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> CheckTypeWellFormedVisitor<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> CheckTypeWellFormedVisitor<'tcx> {
-        CheckTypeWellFormedVisitor { tcx }
-    }
-}
-
-impl<'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
-    fn visit_item(&self, i: &'tcx hir::Item<'tcx>) {
-        Visitor::visit_item(&mut self.clone(), i);
-    }
-
-    fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        Visitor::visit_trait_item(&mut self.clone(), trait_item);
-    }
-
-    fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        Visitor::visit_impl_item(&mut self.clone(), impl_item);
-    }
-
-    fn visit_foreign_item(&self, foreign_item: &'tcx hir::ForeignItem<'tcx>) {
-        Visitor::visit_foreign_item(&mut self.clone(), foreign_item)
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    #[instrument(skip(self, i), level = "debug")]
-    fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
-        trace!(?i);
-        self.tcx.ensure().check_item_well_formed(i.def_id);
-        hir_visit::walk_item(self, i);
-    }
-
-    #[instrument(skip(self, trait_item), level = "debug")]
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        trace!(?trait_item);
-        self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
-        hir_visit::walk_trait_item(self, trait_item);
-    }
-
-    #[instrument(skip(self, impl_item), level = "debug")]
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        trace!(?impl_item);
-        self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
-        hir_visit::walk_impl_item(self, impl_item);
-    }
-
-    fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
-        check_param_wf(self.tcx, p);
-        hir_visit::walk_generic_param(self, p);
-    }
+fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
+    let items = tcx.hir_module_items(module);
+    items.par_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id));
+    items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id));
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1967,3 +1930,7 @@ fn error_392(
     err.span_label(span, "unused parameter");
     err
 }
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
+}
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs
index c089d25d222..e968d73e95f 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check.rs
@@ -54,13 +54,6 @@ mod min_specialization;
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
 /// //   ^ 'a is unused and appears in assoc type, error
 /// ```
-pub fn impl_wf_check(tcx: TyCtxt<'_>) {
-    // We will tag this as part of the WF check -- logically, it is,
-    // but it's one that we must perform earlier than the rest of
-    // WfCheck.
-    tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
-}
-
 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);
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index a7a008bc2eb..b6d4f5fcda6 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -509,7 +509,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("impl_wf_inference", || impl_wf_check::impl_wf_check(tcx));
+        tcx.sess.time("impl_wf_inference", || {
+            tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
+        });
     })?;
 
     tcx.sess.track_errors(|| {
@@ -531,7 +533,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     }
 
     tcx.sess.track_errors(|| {
-        tcx.sess.time("wf_checking", || check::check_wf_new(tcx));
+        tcx.sess.time("wf_checking", || {
+            tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
+        });
     })?;
 
     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.