]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_middle/src/hir/map/mod.rs
Store lowering outputs per owner.
[rust.git] / compiler / rustc_middle / src / hir / map / mod.rs
index 3707fadadac208cf774ce2363aa25582d66cd5fd..9a1bdba824e1d4a7c11a6fb3759cd787c45ddbfd 100644 (file)
@@ -1,11 +1,12 @@
 use self::collector::NodeCollector;
 
-use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
+use crate::hir::{IndexedHir, ModuleItems, Owner};
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
@@ -156,6 +157,21 @@ pub fn krate(&self) -> &'hir Crate<'hir> {
         self.tcx.hir_crate(())
     }
 
+    pub fn root_module(&self) -> &'hir Mod<'hir> {
+        match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) {
+            Some(OwnerNode::Crate(item)) => item,
+            _ => bug!(),
+        }
+    }
+
+    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()?.node {
+            OwnerNode::Item(item) => Some(item),
+            _ => None,
+        })
+    }
+
     pub fn def_key(&self, def_id: LocalDefId) -> DefKey {
         // Accessing the DefKey is ok, since it is part of DefPathHash.
         self.tcx.untracked_resolutions.definitions.def_key(def_id)
@@ -475,6 +491,41 @@ pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
         Some(ccx)
     }
 
+    /// Returns an iterator of the `DefId`s for all body-owners in this
+    /// 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()
+            .owners
+            .iter_enumerated()
+            .flat_map(move |(owner, owner_info)| {
+                let bodies = &owner_info.as_ref()?.bodies;
+                Some(bodies.keys().map(move |&local_id| {
+                    let hir_id = HirId { owner, local_id };
+                    let body_id = BodyId { hir_id };
+                    self.body_owner_def_id(body_id)
+                }))
+            })
+            .flatten()
+    }
+
+    pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
+        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.bodies).for_each(|(&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 {
         match self.get(id) {
             Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id,
@@ -524,13 +575,57 @@ pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'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.iter() {
+                    let id = HirId { owner, local_id };
+                    for a in *attrs {
+                        visitor.visit_attribute(id, a)
+                    }
+                }
             }
         }
     }
 
+    /// Visits all items in the crate in some deterministic (but
+    /// unspecified) order. If you just need to process every item,
+    /// but don't care about nesting, this method is the best choice.
+    ///
+    /// If you do care about nesting -- usually because your algorithm
+    /// follows lexical scoping rules -- then you want a different
+    /// approach. You should override `visit_nested_item` in your
+    /// visitor and then call `intravisit::walk_crate` instead.
+    pub fn visit_all_item_likes<V>(&self, visitor: &mut V)
+    where
+        V: itemlikevisit::ItemLikeVisitor<'hir>,
+    {
+        let krate = self.krate();
+        for owner in krate.owners.iter().filter_map(Option::as_ref) {
+            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),
+                OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
+                OwnerNode::Crate(_) => {}
+            }
+        }
+    }
+
+    /// A parallel version of `visit_all_item_likes`.
+    pub fn par_visit_all_item_likes<V>(&self, visitor: &V)
+    where
+        V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
+    {
+        let krate = self.krate();
+        par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(|o| o.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),
+            Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
+            Some(OwnerNode::Crate(_)) | None => {}
+        })
+    }
+
     pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
     where
         V: ItemLikeVisitor<'hir>,
@@ -1025,7 +1120,10 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     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 }
+        tcx.untracked_crate.owners[*def_id]
+            .as_ref()
+            .unwrap()
+            .attrs
             .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);