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};
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)
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,
/// 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>,
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);