diff options
| author | bors <bors@rust-lang.org> | 2021-10-18 19:53:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-10-18 19:53:05 +0000 |
| commit | bd41e09da334697c0f993b36685cb599061d9faa (patch) | |
| tree | 769f410664dda01f42297c0adf9fbd5dc7f1ace2 /compiler/rustc_middle/src | |
| parent | 5dab47dcd8267b8769421b46532414ec36d625e3 (diff) | |
| parent | 1e2dbb5f4a80077cb4b036b6f4ff96c96ad89805 (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.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/hir/map/collector.rs | 431 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/hir/map/mod.rs | 137 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/hir/mod.rs | 124 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 10 |
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| { |
