about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/arena.rs8
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs224
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs72
-rw-r--r--compiler/rustc_middle/src/hir/map/blocks.rs239
-rw-r--r--compiler/rustc_middle/src/hir/map/collector.rs431
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs141
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs124
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs5
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs8
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/query.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs120
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs12
-rw-r--r--compiler/rustc_middle/src/traits/select.rs10
-rw-r--r--compiler/rustc_middle/src/ty/context.rs45
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/error.rs26
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs45
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs13
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs76
-rw-r--r--compiler/rustc_middle/src/ty/outlives.rs213
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/query.rs60
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs15
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs10
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs1
29 files changed, 612 insertions, 1329 deletions
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index d06c593d394..daeccde6024 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -12,6 +12,7 @@ bitflags = "1.2.1"
 either = "1.5.0"
 gsgdt = "0.1.2"
 tracing = "0.1"
+rustc-rayon = "0.3.1"
 rustc-rayon-core = "0.3.1"
 polonius-engine = "0.13.0"
 rustc_apfloat = { path = "../rustc_apfloat" }
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 962aea448b8..420c500a7de 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -92,12 +92,6 @@ macro_rules! arena_types {
             [] tys: rustc_middle::ty::TyS<$tcx>,
             [] predicates: rustc_middle::ty::PredicateInner<$tcx>,
 
-            // HIR query types
-            [few] indexed_hir: rustc_middle::hir::IndexedHir<$tcx>,
-            [few] hir_definitions: rustc_hir::definitions::Definitions,
-            [] hir_owner: rustc_middle::hir::Owner<$tcx>,
-            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
-
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
@@ -106,6 +100,8 @@ macro_rules! arena_types {
             // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
             [decode] span: rustc_span::Span,
             [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>,
+
+            [] dep_kind: rustc_middle::dep_graph::DepKindStruct,
         ], $tcx);
     )
 }
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 23d475a5953..f3100010770 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -75,145 +75,71 @@ pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
 /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
 /// jump table instead of large matches.
 pub struct DepKindStruct {
-    /// Whether the DepNode has parameters (query keys).
-    pub(super) has_params: bool,
-
     /// Anonymous queries cannot be replayed from one compiler invocation to the next.
     /// When their result is needed, it is recomputed. They are useful for fine-grained
     /// dependency tracking, and caching within one compiler invocation.
-    pub(super) is_anon: bool,
+    pub is_anon: bool,
 
     /// Eval-always queries do not track their dependencies, and are always recomputed, even if
     /// their inputs have not changed since the last compiler invocation. The result is still
     /// cached within one compiler invocation.
-    pub(super) is_eval_always: bool,
+    pub is_eval_always: bool,
 
     /// Whether the query key can be recovered from the hashed fingerprint.
     /// See [DepNodeParams] trait for the behaviour of each key type.
-    // FIXME: Make this a simple boolean once DepNodeParams::fingerprint_style
-    // can be made a specialized associated const.
-    fingerprint_style: fn() -> FingerprintStyle,
-}
-
-impl std::ops::Deref for DepKind {
-    type Target = DepKindStruct;
-    fn deref(&self) -> &DepKindStruct {
-        &DEP_KINDS[*self as usize]
-    }
+    pub fingerprint_style: FingerprintStyle,
+
+    /// The red/green evaluation system will try to mark a specific DepNode in the
+    /// dependency graph as green by recursively trying to mark the dependencies of
+    /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+    /// where we don't know if it is red or green and we therefore actually have
+    /// to recompute its value in order to find out. Since the only piece of
+    /// information that we have at that point is the `DepNode` we are trying to
+    /// re-evaluate, we need some way to re-run a query from just that. This is what
+    /// `force_from_dep_node()` implements.
+    ///
+    /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+    /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+    /// is usually constructed by computing a stable hash of the query-key that the
+    /// `DepNode` corresponds to. Consequently, it is not in general possible to go
+    /// back from hash to query-key (since hash functions are not reversible). For
+    /// this reason `force_from_dep_node()` is expected to fail from time to time
+    /// because we just cannot find out, from the `DepNode` alone, what the
+    /// corresponding query-key is and therefore cannot re-run the query.
+    ///
+    /// The system deals with this case letting `try_mark_green` fail which forces
+    /// the root query to be re-evaluated.
+    ///
+    /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+    /// Fortunately, we can use some contextual information that will allow us to
+    /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+    /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+    /// valid `DefPathHash`. Since we also always build a huge table that maps every
+    /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+    /// everything we need to re-run the query.
+    ///
+    /// Take the `mir_promoted` query as an example. Like many other queries, it
+    /// just has a single parameter: the `DefId` of the item it will compute the
+    /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+    /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+    /// is actually a `DefPathHash`, and can therefore just look up the corresponding
+    /// `DefId` in `tcx.def_path_hash_to_def_id`.
+    pub force_from_dep_node: Option<fn(tcx: TyCtxt<'_>, dep_node: DepNode) -> bool>,
+
+    /// Invoke a query to put the on-disk cached value in memory.
+    pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'_>, DepNode)>,
 }
 
 impl DepKind {
     #[inline(always)]
-    pub fn fingerprint_style(&self) -> FingerprintStyle {
+    pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle {
         // Only fetch the DepKindStruct once.
-        let data: &DepKindStruct = &**self;
+        let data = tcx.query_kind(self);
         if data.is_anon {
             return FingerprintStyle::Opaque;
         }
-
-        (data.fingerprint_style)()
-    }
-}
-
-// erase!() just makes tokens go away. It's used to specify which macro argument
-// is repeated (i.e., which sub-expression of the macro we are in) but don't need
-// to actually use any of the arguments.
-macro_rules! erase {
-    ($x:tt) => {{}};
-}
-
-macro_rules! is_anon_attr {
-    (anon) => {
-        true
-    };
-    ($attr:ident) => {
-        false
-    };
-}
-
-macro_rules! is_eval_always_attr {
-    (eval_always) => {
-        true
-    };
-    ($attr:ident) => {
-        false
-    };
-}
-
-macro_rules! contains_anon_attr {
-    ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_anon_attr!($attr) | )* false});
-}
-
-macro_rules! contains_eval_always_attr {
-    ($(($attr:ident $($attr_args:tt)* )),*) => ({$(is_eval_always_attr!($attr) | )* false});
-}
-
-#[allow(non_upper_case_globals)]
-pub mod dep_kind {
-    use super::*;
-    use crate::ty::query::query_keys;
-    use rustc_query_system::dep_graph::FingerprintStyle;
-
-    // We use this for most things when incr. comp. is turned off.
-    pub const Null: DepKindStruct = DepKindStruct {
-        has_params: false,
-        is_anon: false,
-        is_eval_always: false,
-
-        fingerprint_style: || FingerprintStyle::Unit,
-    };
-
-    pub const TraitSelect: DepKindStruct = DepKindStruct {
-        has_params: false,
-        is_anon: true,
-        is_eval_always: false,
-
-        fingerprint_style: || FingerprintStyle::Unit,
-    };
-
-    pub const CompileCodegenUnit: DepKindStruct = DepKindStruct {
-        has_params: true,
-        is_anon: false,
-        is_eval_always: false,
-
-        fingerprint_style: || FingerprintStyle::Opaque,
-    };
-
-    pub const CompileMonoItem: DepKindStruct = DepKindStruct {
-        has_params: true,
-        is_anon: false,
-        is_eval_always: false,
-
-        fingerprint_style: || FingerprintStyle::Opaque,
-    };
-
-    macro_rules! define_query_dep_kinds {
-        ($(
-            [$($attrs:tt)*]
-            $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
-        ,)*) => (
-            $(pub const $variant: DepKindStruct = {
-                const has_params: bool = $({ erase!($tuple_arg_ty); true } |)* false;
-                const is_anon: bool = contains_anon_attr!($($attrs)*);
-                const is_eval_always: bool = contains_eval_always_attr!($($attrs)*);
-
-                #[inline(always)]
-                fn fingerprint_style() -> rustc_query_system::dep_graph::FingerprintStyle {
-                    <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>
-                        ::fingerprint_style()
-                }
-
-                DepKindStruct {
-                    has_params,
-                    is_anon,
-                    is_eval_always,
-                    fingerprint_style,
-                }
-            };)*
-        );
+        data.fingerprint_style
     }
-
-    rustc_dep_node_append!([define_query_dep_kinds!][]);
 }
 
 macro_rules! define_dep_nodes {
@@ -225,12 +151,10 @@ macro_rules! define_dep_nodes {
     ) => (
         #[macro_export]
         macro_rules! make_dep_kind_array {
-            ($mod:ident) => {[ $(($mod::$variant),)* ]};
+            ($mod:ident) => {[ $($mod::$variant()),* ]};
         }
 
-        static DEP_KINDS: &[DepKindStruct] = &make_dep_kind_array!(dep_kind);
-
-        /// This enum serves as an index into the `DEP_KINDS` array.
+        /// This enum serves as an index into arrays built by `make_dep_kind_array`.
         #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
         #[allow(non_camel_case_types)]
         pub enum DepKind {
@@ -296,7 +220,7 @@ pub trait DepNodeExt: Sized {
     /// Construct a DepNode from the given DepKind and DefPathHash. This
     /// method will assert that the given DepKind actually requires a
     /// single DefId/DefPathHash parameter.
-    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
+    fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self;
 
     /// Extracts the DefId corresponding to this DepNode. This will work
     /// if two conditions are met:
@@ -311,7 +235,11 @@ pub trait DepNodeExt: Sized {
     fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
 
     /// Used in testing
-    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<Self, ()>;
+    fn from_label_string(
+        tcx: TyCtxt<'_>,
+        label: &str,
+        def_path_hash: DefPathHash,
+    ) -> Result<Self, ()>;
 
     /// Used in testing
     fn has_label_string(label: &str) -> bool;
@@ -321,8 +249,8 @@ impl DepNodeExt for DepNode {
     /// Construct a DepNode from the given DepKind and DefPathHash. This
     /// method will assert that the given DepKind actually requires a
     /// single DefId/DefPathHash parameter.
-    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
-        debug_assert!(kind.fingerprint_style() == FingerprintStyle::DefPathHash);
+    fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
+        debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash);
         DepNode { kind, hash: def_path_hash.0.into() }
     }
 
@@ -337,31 +265,27 @@ impl DepNodeExt for DepNode {
     /// refers to something from the previous compilation session that
     /// has been removed.
     fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
-        if self.kind.fingerprint_style() == FingerprintStyle::DefPathHash {
-            Some(
-                tcx.on_disk_cache
-                    .as_ref()?
-                    .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())),
-            )
+        if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash {
+            Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into())))
         } else {
             None
         }
     }
 
     /// Used in testing
-    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
+    fn from_label_string(
+        tcx: TyCtxt<'_>,
+        label: &str,
+        def_path_hash: DefPathHash,
+    ) -> Result<DepNode, ()> {
         let kind = dep_kind_from_label_string(label)?;
 
-        match kind.fingerprint_style() {
+        match kind.fingerprint_style(tcx) {
             FingerprintStyle::Opaque => Err(()),
-            FingerprintStyle::Unit => {
-                if !kind.has_params {
-                    Ok(DepNode::new_no_params(kind))
-                } else {
-                    Err(())
-                }
+            FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)),
+            FingerprintStyle::DefPathHash => {
+                Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind))
             }
-            FingerprintStyle::DefPathHash => Ok(DepNode::from_def_path_hash(def_path_hash, kind)),
         }
     }
 
@@ -377,10 +301,12 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
         FingerprintStyle::Unit
     }
 
+    #[inline(always)]
     fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
         Fingerprint::ZERO
     }
 
+    #[inline(always)]
     fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
         Some(())
     }
@@ -392,14 +318,17 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
         FingerprintStyle::DefPathHash
     }
 
+    #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         tcx.def_path_hash(*self).0
     }
 
+    #[inline(always)]
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.def_path_str(*self)
     }
 
+    #[inline(always)]
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         dep_node.extract_def_id(tcx)
     }
@@ -411,14 +340,17 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
         FingerprintStyle::DefPathHash
     }
 
+    #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         self.to_def_id().to_fingerprint(tcx)
     }
 
+    #[inline(always)]
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         self.to_def_id().to_debug_str(tcx)
     }
 
+    #[inline(always)]
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         dep_node.extract_def_id(tcx).map(|id| id.expect_local())
     }
@@ -430,15 +362,18 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
         FingerprintStyle::DefPathHash
     }
 
+    #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
         def_id.to_fingerprint(tcx)
     }
 
+    #[inline(always)]
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         tcx.crate_name(*self).to_string()
     }
 
+    #[inline(always)]
     fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
         dep_node.extract_def_id(tcx).map(|id| id.krate)
     }
@@ -453,6 +388,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
     // hashing context and stable-hashing state.
+    #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         let (def_id_0, def_id_1) = *self;
 
@@ -462,6 +398,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
         def_path_hash_0.0.combine(def_path_hash_1.0)
     }
 
+    #[inline(always)]
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
         let (def_id_0, def_id_1) = *self;
 
@@ -478,6 +415,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
     // hashing context and stable-hashing state.
+    #[inline(always)]
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         let HirId { owner, local_id } = *self;
 
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index cda99639074..79d7ca32f35 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -12,7 +12,7 @@ pub use rustc_query_system::dep_graph::{
     SerializedDepNodeIndex, WorkProduct, WorkProductId,
 };
 
-pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt};
+pub use dep_node::{label_strs, DepKind, DepKindStruct, DepNode, DepNodeExt};
 crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
 
 pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
@@ -24,29 +24,8 @@ pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
 impl rustc_query_system::dep_graph::DepKind for DepKind {
     const NULL: Self = DepKind::Null;
 
-    #[inline(always)]
-    fn fingerprint_style(&self) -> rustc_query_system::dep_graph::FingerprintStyle {
-        DepKind::fingerprint_style(self)
-    }
-
-    #[inline(always)]
-    fn is_eval_always(&self) -> bool {
-        self.is_eval_always
-    }
-
-    #[inline(always)]
-    fn has_params(&self) -> bool {
-        self.has_params
-    }
-
     fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{:?}", node.kind)?;
-
-        if !node.kind.has_params && !node.kind.is_anon {
-            return Ok(());
-        }
-
-        write!(f, "(")?;
+        write!(f, "{:?}(", node.kind)?;
 
         ty::tls::with_opt(|opt_tcx| {
             if let Some(tcx) = opt_tcx {
@@ -110,4 +89,51 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
     fn sess(&self) -> &Session {
         self.sess
     }
+
+    #[inline(always)]
+    fn fingerprint_style(&self, kind: DepKind) -> rustc_query_system::dep_graph::FingerprintStyle {
+        kind.fingerprint_style(*self)
+    }
+
+    #[inline(always)]
+    fn is_eval_always(&self, kind: DepKind) -> bool {
+        self.query_kind(kind).is_eval_always
+    }
+
+    fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool {
+        debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
+
+        // We must avoid ever having to call `force_from_dep_node()` for a
+        // `DepNode::codegen_unit`:
+        // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+        // would always end up having to evaluate the first caller of the
+        // `codegen_unit` query that *is* reconstructible. This might very well be
+        // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+        // to re-trigger calling the `codegen_unit` query with the right key. At
+        // that point we would already have re-done all the work we are trying to
+        // avoid doing in the first place.
+        // The solution is simple: Just explicitly call the `codegen_unit` query for
+        // each CGU, right after partitioning. This way `try_mark_green` will always
+        // hit the cache instead of having to go through `force_from_dep_node`.
+        // This assertion makes sure, we actually keep applying the solution above.
+        debug_assert!(
+            dep_node.kind != DepKind::codegen_unit,
+            "calling force_from_dep_node() on DepKind::codegen_unit"
+        );
+
+        let cb = self.query_kind(dep_node.kind);
+        if let Some(f) = cb.force_from_dep_node {
+            f(*self, dep_node);
+            true
+        } else {
+            false
+        }
+    }
+
+    fn try_load_from_on_disk_cache(&self, dep_node: DepNode) {
+        let cb = self.query_kind(dep_node.kind);
+        if let Some(f) = cb.try_load_from_on_disk_cache {
+            f(*self, dep_node)
+        }
+    }
 }
diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs
deleted file mode 100644
index 8efec8ef567..00000000000
--- a/compiler/rustc_middle/src/hir/map/blocks.rs
+++ /dev/null
@@ -1,239 +0,0 @@
-//! This module provides a simplified abstraction for working with
-//! code blocks identified by their integer `NodeId`. In particular,
-//! it captures a common set of attributes that all "function-like
-//! things" (represented by `FnLike` instances) share. For example,
-//! all `FnLike` instances have a type signature (be it explicit or
-//! inferred). And all `FnLike` instances have a body, i.e., the code
-//! that is run when the function-like thing it represents is invoked.
-//!
-//! With the above abstraction in place, one can treat the program
-//! text as a collection of blocks of code (and most such blocks are
-//! nested within a uniquely determined `FnLike`), and users can ask
-//! for the `Code` associated with a particular NodeId.
-
-use crate::hir::map::Map;
-use rustc_hir as hir;
-use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Expr, FnDecl, Node};
-use rustc_span::symbol::Ident;
-use rustc_span::Span;
-
-/// An FnLikeNode is a Node that is like a fn, in that it has a decl
-/// and a body (as well as a NodeId, a span, etc).
-///
-/// More specifically, it is one of either:
-///
-///   - A function item,
-///   - A closure expr (i.e., an ExprKind::Closure), or
-///   - The default implementation for a trait method.
-///
-/// To construct one, use the `Code::from_node` function.
-#[derive(Copy, Clone, Debug)]
-pub struct FnLikeNode<'a> {
-    node: Node<'a>,
-}
-
-/// MaybeFnLike wraps a method that indicates if an object
-/// corresponds to some FnLikeNode.
-trait MaybeFnLike {
-    fn is_fn_like(&self) -> bool;
-}
-
-impl MaybeFnLike for hir::Item<'_> {
-    fn is_fn_like(&self) -> bool {
-        matches!(self.kind, hir::ItemKind::Fn(..))
-    }
-}
-
-impl MaybeFnLike for hir::ImplItem<'_> {
-    fn is_fn_like(&self) -> bool {
-        matches!(self.kind, hir::ImplItemKind::Fn(..))
-    }
-}
-
-impl MaybeFnLike for hir::TraitItem<'_> {
-    fn is_fn_like(&self) -> bool {
-        matches!(self.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)))
-    }
-}
-
-impl MaybeFnLike for hir::Expr<'_> {
-    fn is_fn_like(&self) -> bool {
-        matches!(self.kind, hir::ExprKind::Closure(..))
-    }
-}
-
-/// Carries either an FnLikeNode or an Expr, as these are the two
-/// constructs that correspond to "code" (as in, something from which
-/// we can construct a control-flow graph).
-#[derive(Copy, Clone)]
-pub enum Code<'a> {
-    FnLike(FnLikeNode<'a>),
-    Expr(&'a Expr<'a>),
-}
-
-impl<'a> Code<'a> {
-    pub fn id(&self) -> hir::HirId {
-        match *self {
-            Code::FnLike(node) => node.id(),
-            Code::Expr(block) => block.hir_id,
-        }
-    }
-
-    /// Attempts to construct a Code from presumed FnLike or Expr node input.
-    pub fn from_node(map: &Map<'a>, id: hir::HirId) -> Option<Code<'a>> {
-        match map.get(id) {
-            Node::Block(_) => {
-                //  Use the parent, hopefully an expression node.
-                Code::from_node(map, map.get_parent_node(id))
-            }
-            Node::Expr(expr) => Some(Code::Expr(expr)),
-            node => FnLikeNode::from_node(node).map(Code::FnLike),
-        }
-    }
-}
-
-/// These are all the components one can extract from a fn item for
-/// use when implementing FnLikeNode operations.
-struct ItemFnParts<'a> {
-    ident: Ident,
-    decl: &'a hir::FnDecl<'a>,
-    header: hir::FnHeader,
-    vis: &'a hir::Visibility<'a>,
-    generics: &'a hir::Generics<'a>,
-    body: hir::BodyId,
-    id: hir::HirId,
-    span: Span,
-}
-
-/// These are all the components one can extract from a closure expr
-/// for use when implementing FnLikeNode operations.
-struct ClosureParts<'a> {
-    decl: &'a FnDecl<'a>,
-    body: hir::BodyId,
-    id: hir::HirId,
-    span: Span,
-}
-
-impl<'a> ClosureParts<'a> {
-    fn new(d: &'a FnDecl<'a>, b: hir::BodyId, id: hir::HirId, s: Span) -> Self {
-        ClosureParts { decl: d, body: b, id, span: s }
-    }
-}
-
-impl<'a> FnLikeNode<'a> {
-    /// Attempts to construct a FnLikeNode from presumed FnLike node input.
-    pub fn from_node(node: Node<'_>) -> Option<FnLikeNode<'_>> {
-        let fn_like = match node {
-            Node::Item(item) => item.is_fn_like(),
-            Node::TraitItem(tm) => tm.is_fn_like(),
-            Node::ImplItem(it) => it.is_fn_like(),
-            Node::Expr(e) => e.is_fn_like(),
-            _ => false,
-        };
-        fn_like.then_some(FnLikeNode { node })
-    }
-
-    pub fn body(self) -> hir::BodyId {
-        self.handle(
-            |i: ItemFnParts<'a>| i.body,
-            |_, _, _: &'a hir::FnSig<'a>, _, body: hir::BodyId, _| body,
-            |c: ClosureParts<'a>| c.body,
-        )
-    }
-
-    pub fn decl(self) -> &'a FnDecl<'a> {
-        self.handle(
-            |i: ItemFnParts<'a>| &*i.decl,
-            |_, _, sig: &'a hir::FnSig<'a>, _, _, _| &sig.decl,
-            |c: ClosureParts<'a>| c.decl,
-        )
-    }
-
-    pub fn span(self) -> Span {
-        self.handle(
-            |i: ItemFnParts<'_>| i.span,
-            |_, _, _: &'a hir::FnSig<'a>, _, _, span| span,
-            |c: ClosureParts<'_>| c.span,
-        )
-    }
-
-    pub fn id(self) -> hir::HirId {
-        self.handle(
-            |i: ItemFnParts<'_>| i.id,
-            |id, _, _: &'a hir::FnSig<'a>, _, _, _| id,
-            |c: ClosureParts<'_>| c.id,
-        )
-    }
-
-    pub fn constness(self) -> hir::Constness {
-        self.kind().header().map_or(hir::Constness::NotConst, |header| header.constness)
-    }
-
-    pub fn asyncness(self) -> hir::IsAsync {
-        self.kind().header().map_or(hir::IsAsync::NotAsync, |header| header.asyncness)
-    }
-
-    pub fn unsafety(self) -> hir::Unsafety {
-        self.kind().header().map_or(hir::Unsafety::Normal, |header| header.unsafety)
-    }
-
-    pub fn kind(self) -> FnKind<'a> {
-        let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
-            FnKind::ItemFn(p.ident, p.generics, p.header, p.vis)
-        };
-        let closure = |_: ClosureParts<'a>| FnKind::Closure;
-        let method =
-            |_, ident: Ident, sig: &'a hir::FnSig<'a>, vis, _, _| FnKind::Method(ident, sig, vis);
-        self.handle(item, method, closure)
-    }
-
-    fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A
-    where
-        I: FnOnce(ItemFnParts<'a>) -> A,
-        M: FnOnce(
-            hir::HirId,
-            Ident,
-            &'a hir::FnSig<'a>,
-            Option<&'a hir::Visibility<'a>>,
-            hir::BodyId,
-            Span,
-        ) -> A,
-        C: FnOnce(ClosureParts<'a>) -> A,
-    {
-        match self.node {
-            Node::Item(i) => match i.kind {
-                hir::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts {
-                    id: i.hir_id(),
-                    ident: i.ident,
-                    decl: &sig.decl,
-                    body: block,
-                    vis: &i.vis,
-                    span: i.span,
-                    header: sig.header,
-                    generics,
-                }),
-                _ => bug!("item FnLikeNode that is not fn-like"),
-            },
-            Node::TraitItem(ti) => match ti.kind {
-                hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
-                    method(ti.hir_id(), ti.ident, sig, None, body, ti.span)
-                }
-                _ => bug!("trait method FnLikeNode that is not fn-like"),
-            },
-            Node::ImplItem(ii) => match ii.kind {
-                hir::ImplItemKind::Fn(ref sig, body) => {
-                    method(ii.hir_id(), ii.ident, sig, Some(&ii.vis), body, ii.span)
-                }
-                _ => bug!("impl method FnLikeNode that is not fn-like"),
-            },
-            Node::Expr(e) => match e.kind {
-                hir::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => {
-                    closure(ClosureParts::new(&decl, block, e.hir_id, e.span))
-                }
-                _ => bug!("expr FnLikeNode that is not fn-like"),
-            },
-            _ => bug!("other FnLikeNode that is not fn-like"),
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
deleted file mode 100644
index efebf73224f..00000000000
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ /dev/null
@@ -1,431 +0,0 @@
-use crate::arena::Arena;
-use crate::hir::map::Map;
-use crate::hir::{IndexedHir, OwnerNodes, ParentedNode};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_hir::definitions;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::*;
-use rustc_index::vec::{Idx, IndexVec};
-use rustc_query_system::ich::StableHashingContext;
-use rustc_session::Session;
-use rustc_span::source_map::SourceMap;
-use rustc_span::{Span, DUMMY_SP};
-
-use std::iter::repeat;
-
-/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
-pub(super) struct NodeCollector<'a, 'hir> {
-    arena: &'hir Arena<'hir>,
-
-    /// The crate
-    krate: &'hir Crate<'hir>,
-
-    /// Source map
-    source_map: &'a SourceMap,
-
-    map: IndexVec<LocalDefId, Option<&'hir mut OwnerNodes<'hir>>>,
-    parenting: FxHashMap<LocalDefId, HirId>,
-
-    /// The parent of this node
-    parent_node: hir::HirId,
-
-    current_dep_node_owner: LocalDefId,
-
-    definitions: &'a definitions::Definitions,
-
-    hcx: StableHashingContext<'a>,
-}
-
-fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V) {
-    let i = k.index();
-    let len = map.len();
-    if i >= len {
-        map.extend(repeat(None).take(i - len + 1));
-    }
-    debug_assert!(map[k].is_none());
-    map[k] = Some(v);
-}
-
-fn hash_body(
-    hcx: &mut StableHashingContext<'_>,
-    item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
-) -> Fingerprint {
-    let mut stable_hasher = StableHasher::new();
-    hcx.while_hashing_hir_bodies(true, |hcx| {
-        item_like.hash_stable(hcx, &mut stable_hasher);
-    });
-    stable_hasher.finish()
-}
-
-impl<'a, 'hir> NodeCollector<'a, 'hir> {
-    pub(super) fn root(
-        sess: &'a Session,
-        arena: &'hir Arena<'hir>,
-        krate: &'hir Crate<'hir>,
-        definitions: &'a definitions::Definitions,
-        hcx: StableHashingContext<'a>,
-    ) -> NodeCollector<'a, 'hir> {
-        let mut collector = NodeCollector {
-            arena,
-            krate,
-            source_map: sess.source_map(),
-            parent_node: hir::CRATE_HIR_ID,
-            current_dep_node_owner: CRATE_DEF_ID,
-            definitions,
-            hcx,
-            map: IndexVec::from_fn_n(|_| None, definitions.def_index_count()),
-            parenting: FxHashMap::default(),
-        };
-        collector.insert_owner(CRATE_DEF_ID, OwnerNode::Crate(krate.module()));
-
-        collector
-    }
-
-    pub(super) fn finalize_and_compute_crate_hash(mut self) -> IndexedHir<'hir> {
-        // Insert bodies into the map
-        for (id, body) in self.krate.bodies.iter() {
-            let bodies = &mut self.map[id.hir_id.owner].as_mut().unwrap().bodies;
-            assert!(bodies.insert(id.hir_id.local_id, body).is_none());
-        }
-        IndexedHir { map: self.map, parenting: self.parenting }
-    }
-
-    fn insert_owner(&mut self, owner: LocalDefId, node: OwnerNode<'hir>) {
-        let hash = hash_body(&mut self.hcx, node);
-
-        let mut nodes = IndexVec::new();
-        nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: node.into() }));
-
-        debug_assert!(self.map[owner].is_none());
-        self.map[owner] =
-            Some(self.arena.alloc(OwnerNodes { hash, nodes, bodies: FxHashMap::default() }));
-    }
-
-    fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
-        debug_assert_eq!(self.current_dep_node_owner, hir_id.owner);
-        debug_assert_ne!(hir_id.local_id.as_u32(), 0);
-
-        // Make sure that the DepNode of some node coincides with the HirId
-        // owner of that node.
-        if cfg!(debug_assertions) {
-            if hir_id.owner != self.current_dep_node_owner {
-                let node_str = match self.definitions.opt_hir_id_to_local_def_id(hir_id) {
-                    Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate_verbose(),
-                    None => format!("{:?}", node),
-                };
-
-                span_bug!(
-                    span,
-                    "inconsistent DepNode at `{:?}` for `{}`: \
-                     current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
-                    self.source_map.span_to_diagnostic_string(span),
-                    node_str,
-                    self.definitions
-                        .def_path(self.current_dep_node_owner)
-                        .to_string_no_crate_verbose(),
-                    self.current_dep_node_owner,
-                    self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
-                    hir_id.owner,
-                )
-            }
-        }
-
-        let nodes = self.map[hir_id.owner].as_mut().unwrap();
-
-        debug_assert_eq!(self.parent_node.owner, self.current_dep_node_owner);
-        insert_vec_map(
-            &mut nodes.nodes,
-            hir_id.local_id,
-            ParentedNode { parent: self.parent_node.local_id, node: node },
-        );
-    }
-
-    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
-        let parent_node = self.parent_node;
-        self.parent_node = parent_node_id;
-        f(self);
-        self.parent_node = parent_node;
-    }
-
-    fn with_dep_node_owner(&mut self, dep_node_owner: LocalDefId, f: impl FnOnce(&mut Self)) {
-        let prev_owner = self.current_dep_node_owner;
-        let prev_parent = self.parent_node;
-
-        self.current_dep_node_owner = dep_node_owner;
-        self.parent_node = HirId::make_owner(dep_node_owner);
-        f(self);
-        self.current_dep_node_owner = prev_owner;
-        self.parent_node = prev_parent;
-    }
-
-    fn insert_nested(&mut self, item: LocalDefId) {
-        #[cfg(debug_assertions)]
-        {
-            let dk_parent = self.definitions.def_key(item).parent.unwrap();
-            let dk_parent = LocalDefId { local_def_index: dk_parent };
-            let dk_parent = self.definitions.local_def_id_to_hir_id(dk_parent);
-            debug_assert_eq!(
-                dk_parent.owner, self.parent_node.owner,
-                "Different parents for {:?}",
-                item
-            )
-        }
-
-        assert_eq!(self.parenting.insert(item, self.parent_node), None);
-    }
-}
-
-impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
-    type Map = Map<'hir>;
-
-    /// Because we want to track parent items and so forth, enable
-    /// deep walking so that we walk nested items in the context of
-    /// their outer items.
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        panic!("`visit_nested_xxx` must be manually implemented in this visitor");
-    }
-
-    fn visit_nested_item(&mut self, item: ItemId) {
-        debug!("visit_nested_item: {:?}", item);
-        self.insert_nested(item.def_id);
-        self.visit_item(self.krate.item(item));
-    }
-
-    fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
-        self.insert_nested(item_id.def_id);
-        self.visit_trait_item(self.krate.trait_item(item_id));
-    }
-
-    fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
-        self.insert_nested(item_id.def_id);
-        self.visit_impl_item(self.krate.impl_item(item_id));
-    }
-
-    fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
-        self.insert_nested(foreign_id.def_id);
-        self.visit_foreign_item(self.krate.foreign_item(foreign_id));
-    }
-
-    fn visit_nested_body(&mut self, id: BodyId) {
-        self.visit_body(self.krate.body(id));
-    }
-
-    fn visit_param(&mut self, param: &'hir Param<'hir>) {
-        let node = Node::Param(param);
-        self.insert(param.pat.span, param.hir_id, node);
-        self.with_parent(param.hir_id, |this| {
-            intravisit::walk_param(this, param);
-        });
-    }
-
-    fn visit_item(&mut self, i: &'hir Item<'hir>) {
-        debug!("visit_item: {:?}", i);
-        self.insert_owner(i.def_id, OwnerNode::Item(i));
-        self.with_dep_node_owner(i.def_id, |this| {
-            if let ItemKind::Struct(ref struct_def, _) = i.kind {
-                // If this is a tuple or unit-like struct, register the constructor.
-                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
-                    this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
-                }
-            }
-            intravisit::walk_item(this, i);
-        });
-    }
-
-    fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
-        self.insert_owner(fi.def_id, OwnerNode::ForeignItem(fi));
-        self.with_dep_node_owner(fi.def_id, |this| {
-            intravisit::walk_foreign_item(this, fi);
-        });
-    }
-
-    fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) {
-        self.insert(param.span, param.hir_id, Node::GenericParam(param));
-        intravisit::walk_generic_param(self, param);
-    }
-
-    fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
-        self.with_parent(param, |this| {
-            intravisit::walk_const_param_default(this, ct);
-        })
-    }
-
-    fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
-        self.insert_owner(ti.def_id, OwnerNode::TraitItem(ti));
-        self.with_dep_node_owner(ti.def_id, |this| {
-            intravisit::walk_trait_item(this, ti);
-        });
-    }
-
-    fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
-        self.insert_owner(ii.def_id, OwnerNode::ImplItem(ii));
-        self.with_dep_node_owner(ii.def_id, |this| {
-            intravisit::walk_impl_item(this, ii);
-        });
-    }
-
-    fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
-        let node =
-            if let PatKind::Binding(..) = pat.kind { Node::Binding(pat) } else { Node::Pat(pat) };
-        self.insert(pat.span, pat.hir_id, node);
-
-        self.with_parent(pat.hir_id, |this| {
-            intravisit::walk_pat(this, pat);
-        });
-    }
-
-    fn visit_arm(&mut self, arm: &'hir Arm<'hir>) {
-        let node = Node::Arm(arm);
-
-        self.insert(arm.span, arm.hir_id, node);
-
-        self.with_parent(arm.hir_id, |this| {
-            intravisit::walk_arm(this, arm);
-        });
-    }
-
-    fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
-        self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
-
-        self.with_parent(constant.hir_id, |this| {
-            intravisit::walk_anon_const(this, constant);
-        });
-    }
-
-    fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
-        self.insert(expr.span, expr.hir_id, Node::Expr(expr));
-
-        self.with_parent(expr.hir_id, |this| {
-            intravisit::walk_expr(this, expr);
-        });
-    }
-
-    fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
-        self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt));
-
-        self.with_parent(stmt.hir_id, |this| {
-            intravisit::walk_stmt(this, stmt);
-        });
-    }
-
-    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) {
-        if let Some(hir_id) = path_segment.hir_id {
-            self.insert(path_span, hir_id, Node::PathSegment(path_segment));
-        }
-        intravisit::walk_path_segment(self, path_span, path_segment);
-    }
-
-    fn visit_ty(&mut self, ty: &'hir Ty<'hir>) {
-        self.insert(ty.span, ty.hir_id, Node::Ty(ty));
-
-        self.with_parent(ty.hir_id, |this| {
-            intravisit::walk_ty(this, ty);
-        });
-    }
-
-    fn visit_infer(&mut self, inf: &'hir InferArg) {
-        self.insert(inf.span, inf.hir_id, Node::Infer(inf));
-
-        self.with_parent(inf.hir_id, |this| {
-            intravisit::walk_inf(this, inf);
-        });
-    }
-
-    fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
-        self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));
-
-        self.with_parent(tr.hir_ref_id, |this| {
-            intravisit::walk_trait_ref(this, tr);
-        });
-    }
-
-    fn visit_fn(
-        &mut self,
-        fk: intravisit::FnKind<'hir>,
-        fd: &'hir FnDecl<'hir>,
-        b: BodyId,
-        s: Span,
-        id: HirId,
-    ) {
-        assert_eq!(self.parent_node, id);
-        intravisit::walk_fn(self, fk, fd, b, s, id);
-    }
-
-    fn visit_block(&mut self, block: &'hir Block<'hir>) {
-        self.insert(block.span, block.hir_id, Node::Block(block));
-        self.with_parent(block.hir_id, |this| {
-            intravisit::walk_block(this, block);
-        });
-    }
-
-    fn visit_local(&mut self, l: &'hir Local<'hir>) {
-        self.insert(l.span, l.hir_id, Node::Local(l));
-        self.with_parent(l.hir_id, |this| {
-            intravisit::walk_local(this, l);
-        })
-    }
-
-    fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
-        self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
-    }
-
-    fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) {
-        match visibility.node {
-            VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {}
-            VisibilityKind::Restricted { hir_id, .. } => {
-                self.insert(visibility.span, hir_id, Node::Visibility(visibility));
-                self.with_parent(hir_id, |this| {
-                    intravisit::walk_vis(this, visibility);
-                });
-            }
-        }
-    }
-
-    fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) {
-        self.insert(v.span, v.id, Node::Variant(v));
-        self.with_parent(v.id, |this| {
-            // Register the constructor of this variant.
-            if let Some(ctor_hir_id) = v.data.ctor_hir_id() {
-                this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data));
-            }
-            intravisit::walk_variant(this, v, g, item_id);
-        });
-    }
-
-    fn visit_field_def(&mut self, field: &'hir FieldDef<'hir>) {
-        self.insert(field.span, field.hir_id, Node::Field(field));
-        self.with_parent(field.hir_id, |this| {
-            intravisit::walk_field_def(this, field);
-        });
-    }
-
-    fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
-        // Do not visit the duplicate information in TraitItemRef. We want to
-        // map the actual nodes, not the duplicate ones in the *Ref.
-        let TraitItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
-
-        self.visit_nested_trait_item(id);
-    }
-
-    fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
-        // Do not visit the duplicate information in ImplItemRef. We want to
-        // map the actual nodes, not the duplicate ones in the *Ref.
-        let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
-
-        self.visit_nested_impl_item(id);
-    }
-
-    fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
-        // Do not visit the duplicate information in ForeignItemRef. We want to
-        // map the actual nodes, not the duplicate ones in the *Ref.
-        let ForeignItemRef { id, ident: _, span: _ } = *fi;
-
-        self.visit_nested_foreign_item(id);
-    }
-}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index e6f56b0be93..fad7e875fa1 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,6 +1,4 @@
-use self::collector::NodeCollector;
-
-use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
+use crate::hir::{ModuleItems, Owner};
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -22,9 +20,6 @@ use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 use std::collections::VecDeque;
 
-pub mod blocks;
-mod collector;
-
 fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
     match node {
         Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
@@ -166,8 +161,8 @@ impl<'hir> Map<'hir> {
 
     pub fn items(&self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir {
         let krate = self.krate();
-        krate.owners.iter().filter_map(|owner| match owner.as_ref()? {
-            OwnerNode::Item(item) => Some(*item),
+        krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node() {
+            OwnerNode::Item(item) => Some(item),
             _ => None,
         })
     }
@@ -318,7 +313,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
-        self.find_parent_node(hir_id).unwrap_or(CRATE_HIR_ID)
+        self.find_parent_node(hir_id).unwrap()
     }
 
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
@@ -381,7 +376,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap()
+        self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[id.hir_id.local_id].unwrap()
     }
 
     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
@@ -443,7 +438,7 @@ impl<'hir> Map<'hir> {
     pub fn body_param_names(&self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir {
         self.body(id).params.iter().map(|arg| match arg.pat.kind {
             PatKind::Binding(_, _, ident, _) => ident,
-            _ => Ident::new(kw::Empty, rustc_span::DUMMY_SP),
+            _ => Ident::empty(),
         })
     }
 
@@ -495,11 +490,41 @@ impl<'hir> Map<'hir> {
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir().krate().body_ids.iter()`.
     pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
-        self.krate().bodies.keys().map(move |&body_id| self.body_owner_def_id(body_id))
+        self.krate()
+            .owners
+            .iter_enumerated()
+            .flat_map(move |(owner, owner_info)| {
+                let bodies = &owner_info.as_ref()?.nodes.bodies;
+                Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| {
+                    if body.is_none() {
+                        return None;
+                    }
+                    let hir_id = HirId { owner, local_id };
+                    let body_id = BodyId { hir_id };
+                    Some(self.body_owner_def_id(body_id))
+                }))
+            })
+            .flatten()
     }
 
     pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
-        par_for_each_in(&self.krate().bodies, |(&body_id, _)| f(self.body_owner_def_id(body_id)));
+        use rustc_data_structures::sync::{par_iter, ParallelIterator};
+        #[cfg(parallel_compiler)]
+        use rustc_rayon::iter::IndexedParallelIterator;
+
+        par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| {
+            let owner = LocalDefId::new(owner);
+            if let Some(owner_info) = owner_info {
+                par_iter(&owner_info.nodes.bodies.raw).enumerate().for_each(|(local_id, body)| {
+                    if body.is_some() {
+                        let local_id = ItemLocalId::new(local_id);
+                        let hir_id = HirId { owner, local_id };
+                        let body_id = BodyId { hir_id };
+                        f(self.body_owner_def_id(body_id))
+                    }
+                })
+            }
+        });
     }
 
     pub fn ty_param_owner(&self, id: HirId) -> HirId {
@@ -551,9 +576,14 @@ impl<'hir> Map<'hir> {
     /// Walks the attributes in a crate.
     pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
         let krate = self.krate();
-        for (&id, attrs) in krate.attrs.iter() {
-            for a in *attrs {
-                visitor.visit_attribute(id, a)
+        for (owner, info) in krate.owners.iter_enumerated() {
+            if let Some(info) = info {
+                for (&local_id, attrs) in info.attrs.map.iter() {
+                    let id = HirId { owner, local_id };
+                    for a in *attrs {
+                        visitor.visit_attribute(id, a)
+                    }
+                }
             }
         }
     }
@@ -572,7 +602,7 @@ impl<'hir> Map<'hir> {
     {
         let krate = self.krate();
         for owner in krate.owners.iter().filter_map(Option::as_ref) {
-            match owner {
+            match owner.node() {
                 OwnerNode::Item(item) => visitor.visit_item(item),
                 OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
                 OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
@@ -588,7 +618,7 @@ impl<'hir> Map<'hir> {
         V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
     {
         let krate = self.krate();
-        par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref() {
+        par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(OwnerInfo::node) {
             Some(OwnerNode::Item(item)) => visitor.visit_item(item),
             Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
             Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
@@ -839,21 +869,21 @@ impl<'hir> Map<'hir> {
 
     pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> {
         match self.tcx.hir_owner(id.expect_owner()) {
-            Some(Owner { node: OwnerNode::Item(item) }) => item,
+            Some(Owner { node: OwnerNode::Item(item), .. }) => item,
             _ => bug!("expected item, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> {
         match self.tcx.hir_owner(id.expect_owner()) {
-            Some(Owner { node: OwnerNode::ImplItem(item) }) => item,
+            Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
             _ => bug!("expected impl item, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> {
         match self.tcx.hir_owner(id.expect_owner()) {
-            Some(Owner { node: OwnerNode::TraitItem(item) }) => item,
+            Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
             _ => bug!("expected trait item, found {}", self.node_to_string(id)),
         }
     }
@@ -867,7 +897,7 @@ impl<'hir> Map<'hir> {
 
     pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
         match self.tcx.hir_owner(id.expect_owner()) {
-            Some(Owner { node: OwnerNode::ForeignItem(item) }) => item,
+            Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
             _ => bug!("expected foreign item, found {}", self.node_to_string(id)),
         }
     }
@@ -1032,42 +1062,10 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
     }
 }
 
-pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> {
-    let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
-
-    // We can access untracked state since we are an eval_always query.
-    let hcx = tcx.create_stable_hashing_context();
-    let mut collector = NodeCollector::root(
-        tcx.sess,
-        &**tcx.arena,
-        tcx.untracked_crate,
-        &tcx.untracked_resolutions.definitions,
-        hcx,
-    );
-    let top_mod = tcx.untracked_crate.module();
-    collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
-
-    let map = collector.finalize_and_compute_crate_hash();
-    tcx.arena.alloc(map)
-}
-
 pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
-    assert_eq!(crate_num, LOCAL_CRATE);
-
-    // We can access untracked state since we are an eval_always query.
-    let mut hcx = tcx.create_stable_hashing_context();
-
-    let mut hir_body_nodes: Vec<_> = tcx
-        .index_hir(())
-        .map
-        .iter_enumerated()
-        .filter_map(|(def_id, hod)| {
-            let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
-            let hash = hod.as_ref()?.hash;
-            Some((def_path_hash, hash, def_id))
-        })
-        .collect();
-    hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
+    debug_assert_eq!(crate_num, LOCAL_CRATE);
+    let krate = tcx.hir_crate(());
+    let hir_body_hash = krate.hir_hash;
 
     let upstream_crates = upstream_crates(tcx);
 
@@ -1087,20 +1085,27 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
 
     source_file_names.sort_unstable();
 
+    let mut hcx = tcx.create_stable_hashing_context();
     let mut stable_hasher = StableHasher::new();
-    for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
-        def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
-        fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
-        AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
-            .hash_stable(&mut hcx, &mut stable_hasher);
-        if tcx.sess.opts.debugging_opts.incremental_relative_spans {
-            let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
-            debug_assert_eq!(span.parent(), None);
-            span.hash_stable(&mut hcx, &mut stable_hasher);
-        }
-    }
+    hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
     upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
+    if tcx.sess.opts.debugging_opts.incremental_relative_spans {
+        let definitions = &tcx.untracked_resolutions.definitions;
+        let mut owner_spans: Vec<_> = krate
+            .owners
+            .iter_enumerated()
+            .filter_map(|(def_id, info)| {
+                let _ = info.as_ref()?;
+                let def_path_hash = definitions.def_path_hash(def_id);
+                let span = definitions.def_span(def_id);
+                debug_assert_eq!(span.parent(), None);
+                Some((def_path_hash, span))
+            })
+            .collect();
+        owner_spans.sort_unstable_by_key(|bn| bn.0);
+        owner_spans.hash_stable(&mut hcx, &mut stable_hasher);
+    }
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
 
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 5016c5ce954..95d7273b17b 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -8,28 +8,12 @@ pub mod place;
 
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
-use rustc_ast::Attribute;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::*;
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::DUMMY_SP;
-use std::collections::BTreeMap;
-
-/// Result of HIR indexing.
-#[derive(Debug)]
-pub struct IndexedHir<'hir> {
-    /// Contents of the HIR owned by each definition. None for definitions that are not HIR owners.
-    // The `mut` comes from construction time, and is harmless since we only ever hand out
-    // immutable refs to IndexedHir.
-    map: IndexVec<LocalDefId, Option<&'hir mut OwnerNodes<'hir>>>,
-    /// Map from each owner to its parent's HirId inside another owner.
-    // This map is separate from `map` to eventually allow for per-owner indexing.
-    parenting: FxHashMap<LocalDefId, HirId>,
-}
 
 /// Top-level HIR node for current owner. This only contains the node for which
 /// `HirId::local_id == 0`, and excludes bodies.
@@ -39,85 +23,14 @@ pub struct IndexedHir<'hir> {
 #[derive(Copy, Clone, Debug)]
 pub struct Owner<'tcx> {
     node: OwnerNode<'tcx>,
+    hash_without_bodies: Fingerprint,
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
+    #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let Owner { node } = self;
-        hcx.while_hashing_hir_bodies(false, |hcx| node.hash_stable(hcx, hasher));
-    }
-}
-
-/// HIR node coupled with its parent's id in the same HIR owner.
-///
-/// The parent is trash when the node is a HIR owner.
-#[derive(Clone, Debug)]
-pub struct ParentedNode<'tcx> {
-    parent: ItemLocalId,
-    node: Node<'tcx>,
-}
-
-#[derive(Debug)]
-pub struct OwnerNodes<'tcx> {
-    /// Pre-computed hash of the full HIR.
-    hash: Fingerprint,
-    /// Full HIR for the current owner.
-    // The zeroth node's parent is trash, but is never accessed.
-    nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
-    /// Content of local bodies.
-    bodies: FxHashMap<ItemLocalId, &'tcx Body<'tcx>>,
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OwnerNodes<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        // We ignore the `nodes` and `bodies` fields since these refer to information included in
-        // `hash` which is hashed in the collector and used for the crate hash.
-        let OwnerNodes { hash, nodes: _, bodies: _ } = *self;
-        hash.hash_stable(hcx, hasher);
-    }
-}
-
-/// Attributes owner by a HIR owner. It is build as a slice inside the attributes map, restricted
-/// to the nodes whose `HirId::owner` is `prefix`.
-#[derive(Copy, Clone)]
-pub struct AttributeMap<'tcx> {
-    map: &'tcx BTreeMap<HirId, &'tcx [Attribute]>,
-    prefix: LocalDefId,
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for AttributeMap<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let range = self.range();
-
-        range.clone().count().hash_stable(hcx, hasher);
-        for (key, value) in range {
-            key.hash_stable(hcx, hasher);
-            value.hash_stable(hcx, hasher);
-        }
-    }
-}
-
-impl<'tcx> std::fmt::Debug for AttributeMap<'tcx> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("AttributeMap")
-            .field("prefix", &self.prefix)
-            .field("range", &&self.range().collect::<Vec<_>>()[..])
-            .finish()
-    }
-}
-
-impl<'tcx> AttributeMap<'tcx> {
-    fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
-        self.map.get(&HirId { owner: self.prefix, local_id: id }).copied().unwrap_or(&[])
-    }
-
-    fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[Attribute]> {
-        let local_zero = ItemLocalId::from_u32(0);
-        let range = HirId { owner: self.prefix, local_id: local_zero }..HirId {
-            owner: LocalDefId { local_def_index: self.prefix.local_def_index + 1 },
-            local_id: local_zero,
-        };
-        self.map.range(range)
+        let Owner { node: _, hash_without_bodies } = self;
+        hash_without_bodies.hash_stable(hcx, hasher)
     }
 }
 
@@ -149,21 +62,32 @@ pub fn provide(providers: &mut Providers) {
         hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
     };
     providers.hir_crate = |tcx, ()| tcx.untracked_crate;
-    providers.index_hir = map::index_hir;
     providers.crate_hash = map::crate_hash;
     providers.hir_module_items = map::hir_module_items;
     providers.hir_owner = |tcx, id| {
-        let owner = tcx.index_hir(()).map[id].as_ref()?;
-        let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
-        let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
-        Some(Owner { node })
+        let owner = tcx.hir_crate(()).owners[id].as_ref()?;
+        let node = owner.node();
+        Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
     };
-    providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].as_deref();
+    providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes);
     providers.hir_owner_parent = |tcx, id| {
-        let index = tcx.index_hir(());
-        index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
+        // Accessing the def_key is ok since its value is hashed as part of `id`'s DefPathHash.
+        let parent = tcx.untracked_resolutions.definitions.def_key(id).parent;
+        let parent = parent.map_or(CRATE_HIR_ID, |local_def_index| {
+            let def_id = LocalDefId { local_def_index };
+            let mut parent_hir_id =
+                tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id);
+            if let Some(local_id) =
+                tcx.hir_crate(()).owners[parent_hir_id.owner].as_ref().unwrap().parenting.get(&id)
+            {
+                parent_hir_id.local_id = *local_id;
+            }
+            parent_hir_id
+        });
+        parent
     };
-    providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
+    providers.hir_attrs =
+        |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map_or(AttributeMap::EMPTY, |o| &o.attrs);
     providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
     providers.fn_arg_names = |tcx, id| {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index e41f5add457..d90eb839cf6 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -39,6 +39,7 @@
 #![feature(new_uninit)]
 #![feature(nll)]
 #![feature(once_cell)]
+#![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
 #![feature(in_band_lifetimes)]
@@ -55,6 +56,7 @@
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
 #![recursion_limit = "512"]
+#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index b6358f99294..a36c9b6ed73 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -1004,13 +1004,13 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
     /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes`
     /// error which will report the first range of bytes which is uninitialized.
     fn check_init(&self, range: AllocRange) -> AllocResult {
-        self.is_init(range).or_else(|idx_range| {
-            Err(AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
+        self.is_init(range).map_err(|idx_range| {
+            AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
                 access_offset: range.start,
                 access_size: range.size,
                 uninit_offset: idx_range.start,
                 uninit_size: idx_range.end - idx_range.start, // `Size` subtraction
-            })))
+            }))
         })
     }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 5d17bb9b15f..9472a287e5a 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -287,6 +287,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
         target_size: u64,
         data_size: u64,
     },
+    /// A discriminant of an uninhabited enum variant is written.
+    UninhabitedEnumVariantWritten,
 }
 
 impl fmt::Display for UndefinedBehaviorInfo<'_> {
@@ -391,6 +393,9 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
                 "scalar size mismatch: expected {} bytes but got {} bytes instead",
                 target_size, data_size
             ),
+            UninhabitedEnumVariantWritten => {
+                write!(f, "writing discriminant of an uninhabited enum")
+            }
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 67a20d72905..06b42320049 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -47,6 +47,14 @@ pub enum MonoItem<'tcx> {
 }
 
 impl<'tcx> MonoItem<'tcx> {
+    /// Returns `true` if the mono item is user-defined (i.e. not compiler-generated, like shims).
+    pub fn is_user_defined(&self) -> bool {
+        match *self {
+            MonoItem::Fn(instance) => matches!(instance.def, InstanceDef::Item(..)),
+            MonoItem::Static(..) | MonoItem::GlobalAsm(..) => true,
+        }
+    }
+
     pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
         match *self {
             MonoItem::Fn(instance) => {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index db98cb76343..8e363cfbff5 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -71,6 +71,7 @@ pub enum PassWhere {
 ///   or `typeck` appears in the name.
 /// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name
 ///   or `typeck` and `bar` both appear in the name.
+#[inline]
 pub fn dump_mir<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     pass_num: Option<&dyn Display>,
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index d5541d7890c..cb3f3850958 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -225,6 +225,7 @@ pub struct BorrowCheckResult<'tcx> {
 pub struct ConstQualifs {
     pub has_mut_interior: bool,
     pub needs_drop: bool,
+    pub needs_non_const_drop: bool,
     pub custom_eq: bool,
     pub error_occured: Option<ErrorReported>,
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index e3eda8483b6..6d384f5f3d6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -36,18 +36,9 @@ rustc_queries! {
     /// prefer wrappers like `tcx.visit_all_items_in_krate()`.
     query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
         eval_always
-        no_hash
         desc { "get the crate HIR" }
     }
 
-    /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
-    /// Avoid calling this query directly.
-    query index_hir(_: ()) -> &'tcx crate::hir::IndexedHir<'tcx> {
-        eval_always
-        no_hash
-        desc { "index HIR" }
-    }
-
     /// The items in a module.
     ///
     /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
@@ -62,7 +53,6 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_owner(key: LocalDefId) -> Option<crate::hir::Owner<'tcx>> {
-        eval_always
         desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
@@ -71,7 +61,6 @@ rustc_queries! {
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
     query hir_owner_parent(key: LocalDefId) -> hir::HirId {
-        eval_always
         desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
@@ -79,8 +68,7 @@ rustc_queries! {
     ///
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
-    query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx crate::hir::OwnerNodes<'tcx>> {
-        eval_always
+    query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> {
         desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
@@ -88,8 +76,7 @@ rustc_queries! {
     ///
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
-    query hir_attrs(key: LocalDefId) -> rustc_middle::hir::AttributeMap<'tcx> {
-        eval_always
+    query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> {
         desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
@@ -120,6 +107,7 @@ rustc_queries! {
     /// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
     query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> {
         desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param)  }
+        separate_provide_extern
     }
 
     query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
@@ -141,6 +129,7 @@ rustc_queries! {
             path = tcx.def_path_str(key),
         }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     query analysis(key: ()) -> Result<(), ErrorReported> {
@@ -154,6 +143,7 @@ rustc_queries! {
         desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -194,6 +184,7 @@ rustc_queries! {
     /// Bounds from the parent (e.g. with nested impl trait) are not included.
     query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Elaborated version of the predicates from `explicit_item_bounds`.
@@ -222,6 +213,7 @@ rustc_queries! {
 
     query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
         desc { "looking up the native libraries of a linked crate" }
+        separate_provide_extern
     }
 
     query lint_levels(_: ()) -> LintLevelMap {
@@ -239,11 +231,13 @@ rustc_queries! {
         // This query reads from untracked data in definitions.
         eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query is_panic_runtime(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate is_panic_runtime" }
+        separate_provide_extern
     }
 
     /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
@@ -273,6 +267,7 @@ rustc_queries! {
     query mir_const_qualif(key: DefId) -> mir::ConstQualifs {
         desc { |tcx| "const checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
     query mir_const_qualif_const_arg(
         key: (LocalDefId, DefId)
@@ -309,6 +304,7 @@ rustc_queries! {
         desc {
             |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
         }
+        separate_provide_extern
     }
     /// Try to build an abstract representation of the given constant.
     query thir_abstract_const_of_const_arg(
@@ -342,6 +338,7 @@ rustc_queries! {
     ) -> &'tcx mir::Body<'tcx> {
         desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
@@ -379,6 +376,7 @@ rustc_queries! {
     query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
         desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
 
     /// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
@@ -417,6 +415,7 @@ rustc_queries! {
     query promoted_mir(key: DefId) -> &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>> {
         desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
+        separate_provide_extern
     }
     query promoted_mir_of_const_arg(
         key: (LocalDefId, DefId)
@@ -475,12 +474,14 @@ rustc_queries! {
     /// Returns the predicates written explicitly by the user.
     query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns the inferred outlives predicates (e.g., for `struct
     /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
     query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
         desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Maps from the `DefId` of a trait to the list of
@@ -491,6 +492,7 @@ rustc_queries! {
     /// additional acyclicity requirements).
     query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
@@ -516,12 +518,15 @@ rustc_queries! {
     query trait_def(key: DefId) -> ty::TraitDef {
         desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
+        separate_provide_extern
     }
     query adt_def(key: DefId) -> &'tcx ty::AdtDef {
         desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
     query adt_destructor(key: DefId) -> Option<ty::Destructor> {
         desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     // The cycle error here should be reported as an error by `check_representable`.
@@ -550,10 +555,12 @@ rustc_queries! {
     /// `is_const_fn` function.
     query is_const_fn_raw(key: DefId) -> bool {
         desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query asyncness(key: DefId) -> hir::IsAsync {
         desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns `true` if calls to the function may be promoted.
@@ -570,16 +577,19 @@ rustc_queries! {
     /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
     query is_foreign_item(key: DefId) -> bool {
         desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item.
     query static_mutability(def_id: DefId) -> Option<hir::Mutability> {
         desc { |tcx| "looking up static mutability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
     query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
         desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Gets a map with the variance of every item; use `item_variance` instead.
@@ -591,6 +601,7 @@ rustc_queries! {
     /// Maps from the `DefId` of a type or region parameter to its (inferred) variance.
     query variances_of(def_id: DefId) -> &'tcx [ty::Variance] {
         desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Maps from thee `DefId` of a type to its (inferred) outlives.
@@ -602,12 +613,14 @@ rustc_queries! {
     /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items.
     query associated_item_def_ids(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     /// Maps from a trait item to the trait item "descriptor".
     query associated_item(key: DefId) -> ty::AssocItem {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
         storage(ArenaCacheSelector<'tcx>)
+        separate_provide_extern
     }
 
     /// Collects the associated items defined on a trait or impl.
@@ -620,9 +633,11 @@ rustc_queries! {
     /// Return `None` if this is an inherent impl.
     query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
         desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
+        separate_provide_extern
     }
     query impl_polarity(impl_id: DefId) -> ty::ImplPolarity {
         desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) }
+        separate_provide_extern
     }
 
     query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
@@ -635,6 +650,7 @@ rustc_queries! {
     query inherent_impls(key: DefId) -> &'tcx [DefId] {
         desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
         eval_always
+        separate_provide_extern
     }
 
     /// The result of unsafety-checking this `LocalDefId`.
@@ -674,6 +690,7 @@ rustc_queries! {
     /// The signature of functions.
     query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
         desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query lint_mod(key: LocalDefId) -> () {
@@ -728,10 +745,10 @@ rustc_queries! {
     }
 
     /// Caches `CoerceUnsized` kinds for impls on custom types.
-    query coerce_unsized_info(key: DefId)
-        -> ty::adjustment::CoerceUnsizedInfo {
-            desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
-        }
+    query coerce_unsized_info(key: DefId) -> ty::adjustment::CoerceUnsizedInfo {
+        desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
+    }
 
     query typeck_item_bodies(_: ()) -> () {
         desc { "type-checking all item bodies" }
@@ -778,10 +795,7 @@ rustc_queries! {
     /// additional requirements that the closure's creator must verify.
     query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key.to_def_id()) }
-        cache_on_disk_if(tcx, opt_result) {
-            tcx.is_closure(key.to_def_id())
-                || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty())
-        }
+        cache_on_disk_if(tcx) { tcx.is_closure(key.to_def_id()) }
     }
     query mir_borrowck_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::BorrowCheckResult<'tcx> {
         desc {
@@ -929,28 +943,27 @@ rustc_queries! {
 
     query opt_def_kind(def_id: DefId) -> Option<DefKind> {
         desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query def_span(def_id: DefId) -> Span {
         desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
-        // FIXME(mw): DefSpans are not really inputs since they are derived from
-        // HIR. But at the moment HIR hashing still contains some hacks that allow
-        // to make type debuginfo to be source location independent. Declaring
-        // DefSpan an input makes sure that changes to these are always detected
-        // regardless of HIR hashing.
-        eval_always
+        separate_provide_extern
     }
 
     query def_ident_span(def_id: DefId) -> Option<Span> {
         desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> {
         desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> {
         desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query should_inherit_track_caller(def_id: DefId) -> bool {
@@ -959,10 +972,12 @@ rustc_queries! {
 
     query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
         desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] {
         desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
@@ -973,27 +988,33 @@ rustc_queries! {
 
     query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] {
         desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     /// Gets the rendered value of the specified constant or associated constant.
     /// Used by rustdoc.
     query rendered_const(def_id: DefId) -> String {
         desc { |tcx| "rendering constant intializer of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query impl_parent(def_id: DefId) -> Option<DefId> {
         desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Given an `associated_item`, find the trait it belongs to.
     /// Return `None` if the `DefId` is not an associated item.
     query trait_of_item(associated_item: DefId) -> Option<DefId> {
         desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) }
+        separate_provide_extern
     }
 
     query is_ctfe_mir_available(key: DefId) -> bool {
         desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
     query is_mir_available(key: DefId) -> bool {
         desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
+        separate_provide_extern
     }
 
     query own_existential_vtable_entries(
@@ -1159,6 +1180,7 @@ rustc_queries! {
     query dylib_dependency_formats(_: CrateNum)
                                     -> &'tcx [(CrateNum, LinkagePreference)] {
         desc { "dylib dependency formats of crate" }
+        separate_provide_extern
     }
 
     query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
@@ -1168,41 +1190,50 @@ rustc_queries! {
     query is_compiler_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate is_compiler_builtins" }
+        separate_provide_extern
     }
     query has_global_allocator(_: CrateNum) -> bool {
         // This query depends on untracked global state in CStore
         eval_always
         fatal_cycle
         desc { "checking if the crate has_global_allocator" }
+        separate_provide_extern
     }
     query has_panic_handler(_: CrateNum) -> bool {
         fatal_cycle
         desc { "checking if the crate has_panic_handler" }
+        separate_provide_extern
     }
     query is_profiler_runtime(_: CrateNum) -> bool {
         fatal_cycle
         desc { "query a crate is `#![profiler_runtime]`" }
+        separate_provide_extern
     }
     query panic_strategy(_: CrateNum) -> PanicStrategy {
         fatal_cycle
         desc { "query a crate's configured panic strategy" }
+        separate_provide_extern
     }
     query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
         fatal_cycle
         desc { "query a crate's configured panic-in-drop strategy" }
+        separate_provide_extern
     }
     query is_no_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "test whether a crate has `#![no_builtins]`" }
+        separate_provide_extern
     }
     query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion {
         fatal_cycle
         desc { "query a crate's symbol mangling version" }
+        separate_provide_extern
     }
 
     query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> {
         eval_always
         desc { "getting crate's ExternCrateData" }
+        separate_provide_extern
     }
 
     query specializes(_: (DefId, DefId)) -> bool {
@@ -1219,10 +1250,12 @@ rustc_queries! {
 
     query impl_defaultness(def_id: DefId) -> hir::Defaultness {
         desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query impl_constness(def_id: DefId) -> hir::Constness {
         desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     query check_item_well_formed(key: LocalDefId) -> () {
@@ -1251,9 +1284,11 @@ rustc_queries! {
         -> DefIdMap<SymbolExportLevel> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "looking up the exported symbols of a crate" }
+        separate_provide_extern
     }
     query is_reachable_non_generic(def_id: DefId) -> bool {
         desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query is_unreachable_local_definition(def_id: LocalDefId) -> bool {
         desc { |tcx|
@@ -1286,6 +1321,7 @@ rustc_queries! {
                 "collecting available upstream monomorphizations for `{}`",
                 tcx.def_path_str(def_id),
             }
+            separate_provide_extern
         }
 
     /// Returns the upstream crate that exports drop-glue for the given
@@ -1309,6 +1345,7 @@ rustc_queries! {
 
     query foreign_modules(_: CrateNum) -> Lrc<FxHashMap<DefId, ForeignModule>> {
         desc { "looking up the foreign modules of a linked crate" }
+        separate_provide_extern
     }
 
     /// Identifies the entry-point (e.g., the `main` function) for a given
@@ -1324,18 +1361,22 @@ rustc_queries! {
     query crate_hash(_: CrateNum) -> Svh {
         eval_always
         desc { "looking up the hash a crate" }
+        separate_provide_extern
     }
     query crate_host_hash(_: CrateNum) -> Option<Svh> {
         eval_always
         desc { "looking up the hash of a host version of a crate" }
+        separate_provide_extern
     }
     query extra_filename(_: CrateNum) -> String {
         eval_always
         desc { "looking up the extra filename for a crate" }
+        separate_provide_extern
     }
     query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
         eval_always
         desc { "looking up the paths for extern crates" }
+        separate_provide_extern
     }
 
     /// Given a crate and a trait, look up all impls of that trait in the crate.
@@ -1343,6 +1384,7 @@ rustc_queries! {
     query implementations_of_trait(_: (CrateNum, DefId))
         -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
         desc { "looking up implementations of a trait in a crate" }
+        separate_provide_extern
     }
 
     /// Given a crate, look up all trait impls in that crate.
@@ -1350,6 +1392,7 @@ rustc_queries! {
     query all_trait_implementations(_: CrateNum)
         -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
         desc { "looking up all (?) trait implementations" }
+        separate_provide_extern
     }
 
     query is_dllimport_foreign_item(def_id: DefId) -> bool {
@@ -1406,6 +1449,7 @@ rustc_queries! {
 
     query visibility(def_id: DefId) -> ty::Visibility {
         desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
 
     /// Computes the set of modules from which this type is visibly uninhabited.
@@ -1420,13 +1464,16 @@ rustc_queries! {
     query dep_kind(_: CrateNum) -> CrateDepKind {
         eval_always
         desc { "fetching what a dependency looks like" }
+        separate_provide_extern
     }
     query crate_name(_: CrateNum) -> Symbol {
         eval_always
         desc { "fetching what a crate is named" }
+        separate_provide_extern
     }
     query item_children(def_id: DefId) -> &'tcx [Export] {
         desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
+        separate_provide_extern
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
         desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
@@ -1440,6 +1487,7 @@ rustc_queries! {
     query defined_lib_features(_: CrateNum)
         -> &'tcx [(Symbol, Option<Symbol>)] {
         desc { "calculating the lib features defined in a crate" }
+        separate_provide_extern
     }
     /// Returns the lang items defined in another crate by loading it from metadata.
     query get_lang_items(_: ()) -> LanguageItems {
@@ -1458,16 +1506,19 @@ rustc_queries! {
     /// Returns the lang items defined in another crate by loading it from metadata.
     query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
         desc { "calculating the lang items defined in a crate" }
+        separate_provide_extern
     }
 
     /// Returns the diagnostic items defined in a crate.
     query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems {
         storage(ArenaCacheSelector<'tcx>)
         desc { "calculating the diagnostic items map in a crate" }
+        separate_provide_extern
     }
 
     query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] {
         desc { "calculating the missing lang items in a crate" }
+        separate_provide_extern
     }
     query visible_parent_map(_: ()) -> DefIdMap<DefId> {
         storage(ArenaCacheSelector<'tcx>)
@@ -1480,10 +1531,12 @@ rustc_queries! {
     query missing_extern_crate_item(_: CrateNum) -> bool {
         eval_always
         desc { "seeing if we're missing an `extern crate` item for this crate" }
+        separate_provide_extern
     }
     query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
         eval_always
         desc { "looking at the source for a crate" }
+        separate_provide_extern
     }
     query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
@@ -1494,6 +1547,7 @@ rustc_queries! {
     query is_private_dep(c: CrateNum) -> bool {
         eval_always
         desc { "check whether crate {} is a private dependency", c }
+        separate_provide_extern
     }
     query allocator_kind(_: ()) -> Option<AllocatorKind> {
         eval_always
@@ -1539,6 +1593,7 @@ rustc_queries! {
     query exported_symbols(_: CrateNum)
         -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] {
         desc { "exported_symbols" }
+        separate_provide_extern
     }
 
     query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
@@ -1558,12 +1613,13 @@ rustc_queries! {
     query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
         desc { "codegen_unit" }
     }
-    query unused_generic_params(key: DefId) -> FiniteBitSet<u32> {
-        cache_on_disk_if { key.is_local() }
+    query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
+        cache_on_disk_if { key.def_id().is_local() }
         desc {
             |tcx| "determining which generic parameters are unused by `{}`",
-                tcx.def_path_str(key)
+                tcx.def_path_str(key.def_id())
         }
+        separate_provide_extern
     }
     query backend_optimization_level(_: ()) -> OptLevel {
         desc { "optimization level used by backend" }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index b089ae22d6d..6570d8e1567 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -440,16 +440,28 @@ pub struct DerivedObligationCause<'tcx> {
 
 #[derive(Clone, Debug, TypeFoldable, Lift)]
 pub enum SelectionError<'tcx> {
+    /// The trait is not implemented.
     Unimplemented,
+    /// After a closure impl has selected, its "outputs" were evaluated
+    /// (which for closures includes the "input" type params) and they
+    /// didn't resolve. See `confirm_poly_trait_refs` for more.
     OutputTypeParameterMismatch(
         ty::PolyTraitRef<'tcx>,
         ty::PolyTraitRef<'tcx>,
         ty::error::TypeError<'tcx>,
     ),
+    /// The trait pointed by `DefId` is not object safe.
     TraitNotObjectSafe(DefId),
+    /// A given constant couldn't be evaluated.
     NotConstEvaluatable(NotConstEvaluatable),
+    /// Exceeded the recursion depth during type projection.
     Overflow,
+    /// Signaling that an error has already been emitted, to avoid
+    /// multiple errors being shown.
     ErrorReporting,
+    /// Multiple applicable `impl`s where found. The `DefId`s correspond to
+    /// all the `impl`s' Items.
+    Ambiguous(Vec<DefId>),
 }
 
 /// When performing resolution, it is typically the case that there
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 6720493cd3c..560660517f3 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -12,12 +12,14 @@ use rustc_hir::def_id::DefId;
 use rustc_query_system::cache::Cache;
 
 pub type SelectionCache<'tcx> = Cache<
-    ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>,
+    (ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>, ty::ImplPolarity),
     SelectionResult<'tcx, SelectionCandidate<'tcx>>,
 >;
 
-pub type EvaluationCache<'tcx> =
-    Cache<ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, EvaluationResult>;
+pub type EvaluationCache<'tcx> = Cache<
+    (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, ty::ImplPolarity),
+    EvaluationResult,
+>;
 
 /// The selection process begins by considering all impls, where
 /// clauses, and so forth that might resolve an obligation. Sometimes
@@ -101,7 +103,7 @@ pub enum SelectionCandidate<'tcx> {
         /// `false` if there are no *further* obligations.
         has_nested: bool,
     },
-    ParamCandidate(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>),
+    ParamCandidate((ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ty::ImplPolarity)),
     ImplCandidate(DefId),
     AutoImplCandidate(DefId),
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 83d7c307bdf..8240273acad 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1,7 +1,7 @@
 //! Type context book-keeping.
 
 use crate::arena::Arena;
-use crate::dep_graph::DepGraph;
+use crate::dep_graph::{DepGraph, DepKind, DepKindStruct};
 use crate::hir::place::Place as HirPlace;
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
 use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
@@ -79,11 +79,6 @@ pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     where
         Self: Sized;
 
-    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
-    /// session, if it still exists. This is used during incremental compilation to
-    /// turn a deserialized `DefPathHash` into its current `DefId`.
-    fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId;
-
     fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
 
     fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
@@ -1016,6 +1011,7 @@ pub struct GlobalCtxt<'tcx> {
 
     pub queries: &'tcx dyn query::QueryEngine<'tcx>,
     pub query_caches: query::QueryCaches<'tcx>,
+    query_kinds: &'tcx [DepKindStruct],
 
     // Internal caches for metadata decoding. No need to track deps on this.
     pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
@@ -1149,6 +1145,7 @@ impl<'tcx> TyCtxt<'tcx> {
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
+        query_kinds: &'tcx [DepKindStruct],
         crate_name: &str,
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
@@ -1175,6 +1172,7 @@ impl<'tcx> TyCtxt<'tcx> {
             on_disk_cache,
             queries,
             query_caches: query::QueryCaches::default(),
+            query_kinds,
             ty_rcache: Default::default(),
             pred_rcache: Default::default(),
             selection_cache: Default::default(),
@@ -1188,6 +1186,10 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    crate fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct {
+        &self.query_kinds[k as usize]
+    }
+
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
     #[track_caller]
     pub fn ty_error(self) -> Ty<'tcx> {
@@ -1301,6 +1303,27 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
+    /// session, if it still exists. This is used during incremental compilation to
+    /// turn a deserialized `DefPathHash` into its current `DefId`.
+    pub fn def_path_hash_to_def_id(self, hash: DefPathHash) -> DefId {
+        debug!("def_path_hash_to_def_id({:?})", hash);
+
+        let stable_crate_id = hash.stable_crate_id();
+
+        // If this is a DefPathHash from the local crate, we can look up the
+        // DefId in the tcx's `Definitions`.
+        if stable_crate_id == self.sess.local_stable_crate_id() {
+            self.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash).to_def_id()
+        } else {
+            // If this is a DefPathHash from an upstream crate, let the CrateStore map
+            // it to a DefId.
+            let cstore = &self.untracked_resolutions.cstore;
+            let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
+            cstore.def_path_hash_to_def_id(cnum, hash)
+        }
+    }
+
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
         // crate name and stable crate id since this code is called from debug!()
@@ -1337,20 +1360,15 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline(always)]
     pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
-        let krate = self.gcx.untracked_crate;
         let resolutions = &self.gcx.untracked_resolutions;
-
-        StableHashingContext::new(self.sess, krate, &resolutions.definitions, &*resolutions.cstore)
+        StableHashingContext::new(self.sess, &resolutions.definitions, &*resolutions.cstore)
     }
 
     #[inline(always)]
     pub fn create_no_span_stable_hashing_context(self) -> StableHashingContext<'tcx> {
-        let krate = self.gcx.untracked_crate;
         let resolutions = &self.gcx.untracked_resolutions;
-
         StableHashingContext::ignore_spans(
             self.sess,
-            krate,
             &resolutions.definitions,
             &*resolutions.cstore,
         )
@@ -2823,7 +2841,8 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id);
+    providers.in_scope_traits_map =
+        |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|owner_info| &owner_info.trait_map);
     providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
     providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]);
     providers.crate_name = |tcx, id| {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 092eae0fc5c..1b32c8a6698 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -221,9 +221,7 @@ pub fn suggest_constraining_type_param(
 ) -> bool {
     let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
 
-    let param = if let Some(param) = param {
-        param
-    } else {
+    let Some(param) = param else {
         return false;
     };
 
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 08b4d3aecda..2bd9415171d 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -34,6 +34,7 @@ impl<T> ExpectedFound<T> {
 pub enum TypeError<'tcx> {
     Mismatch,
     ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
+    PolarityMismatch(ExpectedFound<ty::ImplPolarity>),
     UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
     AbiMismatch(ExpectedFound<abi::Abi>),
     Mutability,
@@ -104,6 +105,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             ConstnessMismatch(values) => {
                 write!(f, "expected {} bound, found {} bound", values.expected, values.found)
             }
+            PolarityMismatch(values) => {
+                write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
+            }
             UnsafetyMismatch(values) => {
                 write!(f, "expected {} fn, found {} fn", values.expected, values.found)
             }
@@ -212,10 +216,9 @@ impl<'tcx> TypeError<'tcx> {
         use self::TypeError::*;
         match self {
             CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_)
-            | Mismatch | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
-            | IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => {
-                false
-            }
+            | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
+            | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_)
+            | VariadicMismatch(_) | TargetFeatureCast(_) => false,
 
             Mutability
             | ArgumentMutability(_)
@@ -769,11 +772,16 @@ fn foo(&self) -> Self::T { String::new() }
     ) -> bool {
         let assoc = self.associated_item(proj_ty.item_def_id);
         if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
-            let opaque_local_def_id = def_id.expect_local();
-            let opaque_hir_id = self.hir().local_def_id_to_hir_id(opaque_local_def_id);
-            let opaque_hir_ty = match &self.hir().expect_item(opaque_hir_id).kind {
-                hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
-                _ => bug!("The HirId comes from a `ty::Opaque`"),
+            let opaque_local_def_id = def_id.as_local();
+            let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
+                let hir = self.hir();
+                let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id);
+                match &hir.expect_item(opaque_hir_id).kind {
+                    hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
+                    _ => bug!("The HirId comes from a `ty::Opaque`"),
+                }
+            } else {
+                return false;
             };
 
             let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 9b8247fd028..4b38105e447 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -152,6 +152,22 @@ impl<'tcx> InstanceDef<'tcx> {
         }
     }
 
+    /// Returns the `DefId` of instances which might not require codegen locally.
+    pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
+        match self {
+            ty::InstanceDef::Item(def) => Some(def.did),
+            ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id),
+            InstanceDef::VtableShim(..)
+            | InstanceDef::ReifyShim(..)
+            | InstanceDef::FnPtrShim(..)
+            | InstanceDef::Virtual(..)
+            | InstanceDef::Intrinsic(..)
+            | InstanceDef::ClosureOnceShim { .. }
+            | InstanceDef::DropGlue(..)
+            | InstanceDef::CloneShim(..) => None,
+        }
+    }
+
     #[inline]
     pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
         match self {
@@ -567,29 +583,26 @@ impl<'tcx> Instance<'tcx> {
             return self;
         }
 
-        if let InstanceDef::Item(def) = self.def {
-            let polymorphized_substs = polymorphize(tcx, def.did, self.substs);
-            debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
-            Self { def: self.def, substs: polymorphized_substs }
-        } else {
-            self
-        }
+        let polymorphized_substs = polymorphize(tcx, self.def, self.substs);
+        debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
+        Self { def: self.def, substs: polymorphized_substs }
     }
 }
 
 fn polymorphize<'tcx>(
     tcx: TyCtxt<'tcx>,
-    def_id: DefId,
+    instance: ty::InstanceDef<'tcx>,
     substs: SubstsRef<'tcx>,
 ) -> SubstsRef<'tcx> {
-    debug!("polymorphize({:?}, {:?})", def_id, substs);
-    let unused = tcx.unused_generic_params(def_id);
+    debug!("polymorphize({:?}, {:?})", instance, substs);
+    let unused = tcx.unused_generic_params(instance);
     debug!("polymorphize: unused={:?}", unused);
 
     // If this is a closure or generator then we need to handle the case where another closure
     // from the function is captured as an upvar and hasn't been polymorphized. In this case,
     // the unpolymorphized upvar closure would result in a polymorphized closure producing
     // multiple mono items (and eventually symbol clashes).
+    let def_id = instance.def_id();
     let upvars_ty = if tcx.is_closure(def_id) {
         Some(substs.as_closure().tupled_upvars_ty())
     } else if tcx.type_of(def_id).is_generator() {
@@ -613,7 +626,11 @@ fn polymorphize<'tcx>(
             debug!("fold_ty: ty={:?}", ty);
             match ty.kind {
                 ty::Closure(def_id, substs) => {
-                    let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
+                    let polymorphized_substs = polymorphize(
+                        self.tcx,
+                        ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
+                        substs,
+                    );
                     if substs == polymorphized_substs {
                         ty
                     } else {
@@ -621,7 +638,11 @@ fn polymorphize<'tcx>(
                     }
                 }
                 ty::Generator(def_id, substs, movability) => {
-                    let polymorphized_substs = polymorphize(self.tcx, def_id, substs);
+                    let polymorphized_substs = polymorphize(
+                        self.tcx,
+                        ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
+                        substs,
+                    );
                     if substs == polymorphized_substs {
                         ty
                     } else {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d0c7379c2d9..8ec5f4c7978 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -755,17 +755,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     }
 
                     // Extract the number of elements from the layout of the array field:
-                    let len = if let Ok(TyAndLayout {
+                    let Ok(TyAndLayout {
                         layout: Layout { fields: FieldsShape::Array { count, .. }, .. },
                         ..
-                    }) = self.layout_of(f0_ty)
-                    {
-                        count
-                    } else {
+                    }) = self.layout_of(f0_ty) else {
                         return Err(LayoutError::Unknown(ty));
                     };
 
-                    (*e_ty, *len, true)
+                    (*e_ty, *count, true)
                 } else {
                     // First ADT field is not an array:
                     (f0_ty, def.non_enum_variant().fields.len() as _, false)
@@ -787,9 +784,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
                 // Compute the ABI of the element type:
                 let e_ly = self.layout_of(e_ty)?;
-                let e_abi = if let Abi::Scalar(scalar) = e_ly.abi {
-                    scalar
-                } else {
+                let Abi::Scalar(e_abi) = e_ly.abi else {
                     // This error isn't caught in typeck, e.g., if
                     // the element type of the vector is generic.
                     tcx.sess.fatal(&format!(
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e95493acbb7..cf47da157d1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -38,7 +38,7 @@ use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::cstore::CrateStoreDyn;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use rustc_target::abi::Align;
 
 use std::cmp::Ordering;
@@ -92,7 +92,6 @@ pub mod fold;
 pub mod inhabitedness;
 pub mod layout;
 pub mod normalize_erasing_regions;
-pub mod outlives;
 pub mod print;
 pub mod query;
 pub mod relate;
@@ -165,7 +164,18 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
+#[derive(
+    Copy,
+    Clone,
+    PartialEq,
+    Eq,
+    Hash,
+    TyEncodable,
+    TyDecodable,
+    HashStable,
+    Debug,
+    TypeFoldable
+)]
 pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
@@ -178,6 +188,27 @@ pub enum ImplPolarity {
     Reservation,
 }
 
+impl ImplPolarity {
+    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
+    pub fn flip(&self) -> Option<ImplPolarity> {
+        match self {
+            ImplPolarity::Positive => Some(ImplPolarity::Negative),
+            ImplPolarity::Negative => Some(ImplPolarity::Positive),
+            ImplPolarity::Reservation => None,
+        }
+    }
+}
+
+impl fmt::Display for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive => f.write_str("positive"),
+            Self::Negative => f.write_str("negative"),
+            Self::Reservation => f.write_str("reservation"),
+        }
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
@@ -460,6 +491,29 @@ impl<'tcx> Predicate<'tcx> {
     pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
         self.inner.kind
     }
+
+    /// Flips the polarity of a Predicate.
+    ///
+    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
+    pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
+        let kind = self
+            .inner
+            .kind
+            .map_bound(|kind| match kind {
+                PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => {
+                    Some(PredicateKind::Trait(TraitPredicate {
+                        trait_ref,
+                        constness,
+                        polarity: polarity.flip()?,
+                    }))
+                }
+
+                _ => None,
+            })
+            .transpose()?;
+
+        Some(tcx.mk_predicate(kind))
+    }
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
@@ -655,6 +709,8 @@ pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>,
 
     pub constness: BoundConstness,
+
+    pub polarity: ImplPolarity,
 }
 
 pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
@@ -789,7 +845,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
     fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
         self.value
             .map_bound(|trait_ref| {
-                PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: self.constness })
+                PredicateKind::Trait(ty::TraitPredicate {
+                    trait_ref,
+                    constness: self.constness,
+                    polarity: ty::ImplPolarity::Positive,
+                })
             })
             .to_predicate(tcx)
     }
@@ -1900,6 +1960,14 @@ impl<'tcx> TyCtxt<'tcx> {
         self.sess.contains_name(&self.get_attrs(did), attr)
     }
 
+    /// Determines whether an item is annotated with `doc(hidden)`.
+    pub fn is_doc_hidden(self, did: DefId) -> bool {
+        self.get_attrs(did)
+            .iter()
+            .filter_map(|attr| if attr.has_name(sym::doc) { attr.meta_item_list() } else { None })
+            .any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
+    }
+
     /// Returns `true` if this is an `auto trait`.
     pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
         self.trait_def(trait_def_id).has_auto_impl
diff --git a/compiler/rustc_middle/src/ty/outlives.rs b/compiler/rustc_middle/src/ty/outlives.rs
deleted file mode 100644
index ef4ad998f10..00000000000
--- a/compiler/rustc_middle/src/ty/outlives.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-// The outlines relation `T: 'a` or `'a: 'b`. This code frequently
-// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
-// RFC for reference.
-
-use crate::ty::subst::{GenericArg, GenericArgKind};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc_data_structures::sso::SsoHashSet;
-use smallvec::SmallVec;
-
-#[derive(Debug)]
-pub enum Component<'tcx> {
-    Region(ty::Region<'tcx>),
-    Param(ty::ParamTy),
-    UnresolvedInferenceVariable(ty::InferTy),
-
-    // Projections like `T::Foo` are tricky because a constraint like
-    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
-    // where-clause that says `T::Foo: 'a`, or the defining trait may
-    // include a bound like `type Foo: 'static`, or -- in the most
-    // conservative way -- we can prove that `T: 'a` (more generally,
-    // that all components in the projection outlive `'a`). This code
-    // is not in a position to judge which is the best technique, so
-    // we just product the projection as a component and leave it to
-    // the consumer to decide (but see `EscapingProjection` below).
-    Projection(ty::ProjectionTy<'tcx>),
-
-    // In the case where a projection has escaping regions -- meaning
-    // regions bound within the type itself -- we always use
-    // the most conservative rule, which requires that all components
-    // outlive the bound. So for example if we had a type like this:
-    //
-    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
-    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
-    //
-    // then the inner projection (underlined) has an escaping region
-    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
-    // outlives `'b: 'c`, and we don't consider whether the trait
-    // declares that `Foo: 'static` etc. Therefore, we just return the
-    // free components of such a projection (in this case, `'b`).
-    //
-    // However, in the future, we may want to get smarter, and
-    // actually return a "higher-ranked projection" here. Therefore,
-    // we mark that these components are part of an escaping
-    // projection, so that implied bounds code can avoid relying on
-    // them. This gives us room to improve the regionck reasoning in
-    // the future without breaking backwards compat.
-    EscapingProjection(Vec<Component<'tcx>>),
-}
-
-impl<'tcx> TyCtxt<'tcx> {
-    /// Push onto `out` all the things that must outlive `'a` for the condition
-    /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-    pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
-        let mut visited = SsoHashSet::new();
-        compute_components(self, ty0, out, &mut visited);
-        debug!("components({:?}) = {:?}", ty0, out);
-    }
-}
-
-fn compute_components(
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    // Descend through the types, looking for the various "base"
-    // components and collecting them into `out`. This is not written
-    // with `collect()` because of the need to sometimes skip subtrees
-    // in the `subtys` iterator (e.g., when encountering a
-    // projection).
-    match *ty.kind() {
-            ty::FnDef(_, substs) => {
-                // HACK(eddyb) ignore lifetimes found shallowly in `substs`.
-                // This is inconsistent with `ty::Adt` (including all substs)
-                // and with `ty::Closure` (ignoring all substs other than
-                // upvars, of which a `ty::FnDef` doesn't have any), but
-                // consistent with previous (accidental) behavior.
-                // See https://github.com/rust-lang/rust/issues/70917
-                // for further background and discussion.
-                for child in substs {
-                    match child.unpack() {
-                        GenericArgKind::Type(ty) => {
-                            compute_components(tcx, ty, out, visited);
-                        }
-                        GenericArgKind::Lifetime(_) => {}
-                        GenericArgKind::Const(_) => {
-                            compute_components_recursive(tcx, child, out, visited);
-                        }
-                    }
-                }
-            }
-
-            ty::Array(element, _) => {
-                // Don't look into the len const as it doesn't affect regions
-                compute_components(tcx, element, out, visited);
-            }
-
-            ty::Closure(_, ref substs) => {
-                let tupled_ty = substs.as_closure().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-            }
-
-            ty::Generator(_, ref substs, _) => {
-                // Same as the closure case
-                let tupled_ty = substs.as_generator().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-
-                // We ignore regions in the generator interior as we don't
-                // want these to affect region inference
-            }
-
-            // All regions are bound inside a witness
-            ty::GeneratorWitness(..) => (),
-
-            // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
-            // is implied by the environment is done in regionck.
-            ty::Param(p) => {
-                out.push(Component::Param(p));
-            }
-
-            // For projections, we prefer to generate an obligation like
-            // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
-            // regionck more ways to prove that it holds. However,
-            // regionck is not (at least currently) prepared to deal with
-            // higher-ranked regions that may appear in the
-            // trait-ref. Therefore, if we see any higher-ranke regions,
-            // we simply fallback to the most restrictive rule, which
-            // requires that `Pi: 'a` for all `i`.
-            ty::Projection(ref data) => {
-                if !data.has_escaping_bound_vars() {
-                    // best case: no escaping regions, so push the
-                    // projection and skip the subtree (thus generating no
-                    // constraints for Pi). This defers the choice between
-                    // the rules OutlivesProjectionEnv,
-                    // OutlivesProjectionTraitDef, and
-                    // OutlivesProjectionComponents to regionck.
-                    out.push(Component::Projection(*data));
-                } else {
-                    // fallback case: hard code
-                    // OutlivesProjectionComponents.  Continue walking
-                    // through and constrain Pi.
-                    let mut subcomponents = smallvec![];
-                    let mut subvisited = SsoHashSet::new();
-                    compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
-                    out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
-                }
-            }
-
-            // We assume that inference variables are fully resolved.
-            // So, if we encounter an inference variable, just record
-            // the unresolved variable as a component.
-            ty::Infer(infer_ty) => {
-                out.push(Component::UnresolvedInferenceVariable(infer_ty));
-            }
-
-            // Most types do not introduce any region binders, nor
-            // involve any other subtle cases, and so the WF relation
-            // simply constraints any regions referenced directly by
-            // the type and then visits the types that are lexically
-            // contained within. (The comments refer to relevant rules
-            // from RFC1214.)
-            ty::Bool |            // OutlivesScalar
-            ty::Char |            // OutlivesScalar
-            ty::Int(..) |         // OutlivesScalar
-            ty::Uint(..) |        // OutlivesScalar
-            ty::Float(..) |       // OutlivesScalar
-            ty::Never |           // ...
-            ty::Adt(..) |         // OutlivesNominalType
-            ty::Opaque(..) |      // OutlivesNominalType (ish)
-            ty::Foreign(..) |     // OutlivesNominalType
-            ty::Str |             // OutlivesScalar (ish)
-            ty::Slice(..) |       // ...
-            ty::RawPtr(..) |      // ...
-            ty::Ref(..) |         // OutlivesReference
-            ty::Tuple(..) |       // ...
-            ty::FnPtr(_) |        // OutlivesFunction (*)
-            ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*)
-            ty::Placeholder(..) |
-            ty::Bound(..) |
-            ty::Error(_) => {
-                // (*) Function pointers and trait objects are both binders.
-                // In the RFC, this means we would add the bound regions to
-                // the "bound regions list".  In our representation, no such
-                // list is maintained explicitly, because bound regions
-                // themselves can be readily identified.
-                compute_components_recursive(tcx, ty.into(), out, visited);
-            }
-        }
-}
-
-fn compute_components_recursive(
-    tcx: TyCtxt<'tcx>,
-    parent: GenericArg<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    for child in parent.walk_shallow(tcx, visited) {
-        match child.unpack() {
-            GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out, visited);
-            }
-            GenericArgKind::Lifetime(lt) => {
-                // Ignore late-bound regions.
-                if !lt.is_late_bound() {
-                    out.push(Component::Region(lt));
-                }
-            }
-            GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out, visited);
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2610a76b281..b11a54d5dcb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -350,18 +350,26 @@ pub trait PrettyPrinter<'tcx>:
             match self.tcx().extern_crate(def_id) {
                 Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
                     (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
-                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
-                        return Ok((
-                            if !span.is_dummy() {
-                                self.print_def_path(def_id, &[])?
-                            } else {
-                                self.path_crate(cnum)?
-                            },
-                            true,
-                        ));
+                        // NOTE(eddyb) the only reason `span` might be dummy,
+                        // that we're aware of, is that it's the `std`/`core`
+                        // `extern crate` injected by default.
+                        // FIXME(eddyb) find something better to key this on,
+                        // or avoid ending up with `ExternCrateSource::Extern`,
+                        // for the injected `std`/`core`.
+                        if span.is_dummy() {
+                            return Ok((self.path_crate(cnum)?, true));
+                        }
+
+                        // Disable `try_print_trimmed_def_path` behavior within
+                        // the `print_def_path` call, to avoid infinite recursion
+                        // in cases where the `extern crate foo` has non-trivial
+                        // parents, e.g. it's nested in `impl foo::Trait for Bar`
+                        // (see also issues #55779 and #87932).
+                        self = with_no_visible_paths(|| self.print_def_path(def_id, &[]))?;
+
+                        return Ok((self, true));
                     }
                     (ExternCrateSource::Path, LOCAL_CRATE) => {
-                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
                         return Ok((self.path_crate(cnum)?, true));
                     }
                     _ => {}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index b1bc073ca99..34f80627197 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -102,6 +102,10 @@ impl TyCtxt<'tcx> {
     }
 }
 
+/// Helper for `TyCtxtEnsure` to avoid a closure.
+#[inline(always)]
+fn noop<T>(_: &T) {}
+
 macro_rules! query_helper_param_ty {
     (DefId) => { impl IntoQueryParam<DefId> };
     ($K:ty) => { $K };
@@ -119,6 +123,39 @@ macro_rules! query_storage {
     };
 }
 
+macro_rules! separate_provide_extern_decl {
+    ([][$name:ident]) => {
+        ()
+    };
+    ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
+        for<'tcx> fn(
+            TyCtxt<'tcx>,
+            query_keys::$name<'tcx>,
+        ) -> query_values::$name<'tcx>
+    };
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        separate_provide_extern_decl!([$($modifiers)*][$($args)*])
+    };
+}
+
+macro_rules! separate_provide_extern_default {
+    ([][$name:ident]) => {
+        ()
+    };
+    ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
+        |_, key| bug!(
+            "`tcx.{}({:?})` unsupported by its crate; \
+             perhaps the `{}` query was never assigned a provider function",
+            stringify!($name),
+            key,
+            stringify!($name),
+        )
+    };
+    ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
+        separate_provide_extern_default!([$($modifiers)*][$($args)*])
+    };
+}
+
 macro_rules! define_callbacks {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -165,7 +202,7 @@ macro_rules! define_callbacks {
             #[inline(always)]
             pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
                 let key = key.into_query_param();
-                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |_| {});
+                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
 
                 let lookup = match cached {
                     Ok(()) => return,
@@ -192,9 +229,7 @@ macro_rules! define_callbacks {
             pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
             {
                 let key = key.into_query_param();
-                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, |value| {
-                    value.clone()
-                });
+                let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone);
 
                 let lookup = match cached {
                     Ok(value) => return value,
@@ -212,6 +247,10 @@ macro_rules! define_callbacks {
             ) -> query_values::$name<'tcx>,)*
         }
 
+        pub struct ExternProviders {
+            $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
+        }
+
         impl Default for Providers {
             fn default() -> Self {
                 Providers {
@@ -226,11 +265,24 @@ macro_rules! define_callbacks {
             }
         }
 
+        impl Default for ExternProviders {
+            fn default() -> Self {
+                ExternProviders {
+                    $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
+                }
+            }
+        }
+
         impl Copy for Providers {}
         impl Clone for Providers {
             fn clone(&self) -> Self { *self }
         }
 
+        impl Copy for ExternProviders {}
+        impl Clone for ExternProviders {
+            fn clone(&self) -> Self { *self }
+        }
+
         pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
             fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 2c786538014..8b20e1eec9a 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -797,6 +797,20 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
     }
 }
 
+impl<'tcx> Relate<'tcx> for ty::ImplPolarity {
+    fn relate<R: TypeRelation<'tcx>>(
+        relation: &mut R,
+        a: ty::ImplPolarity,
+        b: ty::ImplPolarity,
+    ) -> RelateResult<'tcx, ty::ImplPolarity> {
+        if a != b {
+            Err(TypeError::PolarityMismatch(expected_found(relation, a, b)))
+        } else {
+            Ok(a)
+        }
+    }
+}
+
 impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
@@ -806,6 +820,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
         Ok(ty::TraitPredicate {
             trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
             constness: relation.relate(a.constness, b.constness)?,
+            polarity: relation.relate(a.polarity, b.polarity)?,
         })
     }
 }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 8f343ba9fec..d6069395474 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -157,7 +157,7 @@ impl fmt::Debug for ty::TraitPredicate<'tcx> {
         if let ty::BoundConstness::ConstIfConst = self.constness {
             write!(f, "~const ")?;
         }
-        write!(f, "TraitPredicate({:?})", self.trait_ref)
+        write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
     }
 }
 
@@ -365,8 +365,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
 impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
     type Lifted = ty::TraitPredicate<'tcx>;
     fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
-        tcx.lift(self.trait_ref)
-            .map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness })
+        tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate {
+            trait_ref,
+            constness: self.constness,
+            polarity: self.polarity,
+        })
     }
 }
 
@@ -591,6 +594,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
         Some(match self {
             Mismatch => Mismatch,
             ConstnessMismatch(x) => ConstnessMismatch(x),
+            PolarityMismatch(x) => PolarityMismatch(x),
             UnsafetyMismatch(x) => UnsafetyMismatch(x),
             AbiMismatch(x) => AbiMismatch(x),
             Mutability => Mutability,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d3094b3e6ff..874de3366d7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -882,6 +882,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
         self.map_bound(|trait_ref| ty::TraitPredicate {
             trait_ref,
             constness: ty::BoundConstness::NotConst,
+            polarity: ty::ImplPolarity::Positive,
         })
     }
 }