about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-10-18 19:53:05 +0000
committerbors <bors@rust-lang.org>2021-10-18 19:53:05 +0000
commitbd41e09da334697c0f993b36685cb599061d9faa (patch)
tree769f410664dda01f42297c0adf9fbd5dc7f1ace2 /compiler/rustc_middle/src
parent5dab47dcd8267b8769421b46532414ec36d625e3 (diff)
parent1e2dbb5f4a80077cb4b036b6f4ff96c96ad89805 (diff)
Auto merge of #89124 - cjgillot:owner-info, r=michaelwoerister
Index and hash HIR as part of lowering

Part of https://github.com/rust-lang/rust/pull/88186
~Based on https://github.com/rust-lang/rust/pull/88880 (see merge commit).~

Once HIR is lowered, it is later indexed by the `index_hir` query and hashed for `crate_hash`. This PR moves those post-processing steps to lowering itself. As a side objective, the HIR crate data structure is refactored as an `IndexVec<LocalDefId, Option<OwnerInfo<'hir>>>` where `OwnerInfo` stores all the relevant information for an HIR owner.

r? `@michaelwoerister`
cc `@petrochenkov`
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/arena.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/collector.rs431
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs137
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs124
-rw-r--r--compiler/rustc_middle/src/query/mod.rs23
-rw-r--r--compiler/rustc_middle/src/ty/context.rs10
6 files changed, 101 insertions, 630 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 962aea448b8..4a027cb7ebe 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)
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 c30ab4c957a..38bc01b9b53 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;
@@ -23,7 +21,6 @@ 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 {
@@ -166,8 +163,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 +315,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 +378,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>> {
@@ -495,11 +492,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 +578,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 +604,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 +620,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 +871,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 +899,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 +1064,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 +1087,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/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4145cbd4249..18be9817c5f 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()) }
     }
 
@@ -933,12 +920,6 @@ rustc_queries! {
 
     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
     }
 
     query def_ident_span(def_id: DefId) -> Option<Span> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 83d7c307bdf..14a7e0ef170 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1337,20 +1337,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 +2818,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| {