From 54c3299b3aed464b5c658c2dbfc1a270fb4c051f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 6 Jun 2021 13:48:00 +0200 Subject: Remove eval_always for HIR queries. They depend on `hir_crate` and `index_hir`. --- compiler/rustc_middle/src/query/mod.rs | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'compiler/rustc_middle/src/query') diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9b0b1377875..7e9391b98f7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -62,7 +62,6 @@ rustc_queries! { /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. query hir_owner(key: LocalDefId) -> Option> { - eval_always desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -71,7 +70,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()) } } @@ -80,7 +78,6 @@ 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 desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -89,7 +86,6 @@ 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 desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -933,12 +929,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 { -- cgit 1.4.1-3-g733a5 From c09eaea484c8f7a01741188982447eec88b5caa8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 28 Feb 2021 20:23:10 +0100 Subject: Make index_hir incremental. --- compiler/rustc_hir/src/definitions.rs | 6 + compiler/rustc_middle/src/arena.rs | 5 +- compiler/rustc_middle/src/hir/map/collector.rs | 164 ++++++++++--------------- compiler/rustc_middle/src/hir/map/mod.rs | 43 +++---- compiler/rustc_middle/src/hir/mod.rs | 36 +++--- compiler/rustc_middle/src/query/mod.rs | 3 +- 6 files changed, 115 insertions(+), 142 deletions(-) (limited to 'compiler/rustc_middle/src/query') diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index ca29351455e..b7bdc9a1414 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -92,6 +92,12 @@ impl DefPathTable { .iter_enumerated() .map(move |(index, key)| (index, key, &self.def_path_hashes[index])) } + + pub fn all_def_path_hashes_and_def_ids( + &self, + ) -> impl Iterator + '_ { + self.def_path_hashes.iter_enumerated().map(move |(index, hash)| (hash, index)) + } } /// The definition table containing node definitions. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 962aea448b8..2986e8c7a06 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -93,10 +93,7 @@ macro_rules! arena_types { [] 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>, + [] indexed_hir: rustc_middle::hir::IndexedHir<$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 diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 2499ef8bc60..a9e676b9e30 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -1,10 +1,8 @@ -use crate::arena::Arena; use crate::hir::map::Map; use crate::hir::{IndexedHir, OwnerNodes, ParentedNode}; use rustc_data_structures::fx::FxHashMap; 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::*; @@ -17,21 +15,19 @@ 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>>, - parenting: FxHashMap, + nodes: OwnerNodes<'hir>, + parenting: FxHashMap, /// The parent of this node - parent_node: hir::HirId, + parent_node: hir::ItemLocalId, - current_dep_node_owner: LocalDefId, + owner: LocalDefId, definitions: &'a definitions::Definitions, } @@ -46,53 +42,51 @@ fn insert_vec_map(map: &mut IndexVec>, k: K, v: V map[k] = Some(v); } -impl<'a, 'hir: 'a> NodeCollector<'a, 'hir> { - pub(super) fn root( - sess: &'a Session, - arena: &'hir Arena<'hir>, - krate: &'hir Crate<'hir>, - definitions: &'a definitions::Definitions, - ) -> 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, - 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(self) -> IndexedHir<'hir> { - IndexedHir { map: self.map, parenting: self.parenting } - } - - fn insert_owner(&mut self, owner: LocalDefId, node: OwnerNode<'hir>) { - let mut nodes = IndexVec::new(); - nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: node.into() })); - - let info = self.krate.owners[owner].as_ref().unwrap(); - let hash = info.hash; - let node_hash = info.node_hash; - let bodies = &info.bodies; - - debug_assert!(self.map[owner].is_none()); - self.map[owner] = Some(self.arena.alloc(OwnerNodes { hash, node_hash, nodes, bodies })); - } +pub(super) fn collect<'a, 'hir: 'a>( + sess: &'a Session, + krate: &'hir Crate<'hir>, + definitions: &'a definitions::Definitions, + owner: LocalDefId, +) -> Option> { + let info = krate.owners.get(owner)?.as_ref()?; + let item = info.node; + let mut nodes = IndexVec::new(); + nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: item.into() })); + let mut collector = NodeCollector { + krate, + source_map: sess.source_map(), + owner, + parent_node: ItemLocalId::new(0), + definitions, + nodes: OwnerNodes { + hash: info.hash, + node_hash: info.node_hash, + nodes, + bodies: &info.bodies, + }, + parenting: FxHashMap::default(), + }; + + match item { + OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID), + OwnerNode::Item(item) => collector.visit_item(item), + OwnerNode::TraitItem(item) => collector.visit_trait_item(item), + OwnerNode::ImplItem(item) => collector.visit_impl_item(item), + OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), + }; + + Some(IndexedHir { nodes: collector.nodes, parenting: collector.parenting }) +} +impl<'a, 'hir> NodeCollector<'a, 'hir> { 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_eq!(self.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 { + if hir_id.owner != self.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), @@ -104,62 +98,41 @@ impl<'a, 'hir: 'a> NodeCollector<'a, 'hir> { 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(self.owner).to_string_no_crate_verbose(), + self.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, + &mut self.nodes.nodes, hir_id.local_id, - ParentedNode { parent: self.parent_node.local_id, node: node }, + ParentedNode { parent: self.parent_node, node: node }, ); } fn with_parent(&mut self, parent_node_id: HirId, f: F) { + debug_assert_eq!(parent_node_id.owner, self.owner); let parent_node = self.parent_node; - self.parent_node = parent_node_id; + self.parent_node = parent_node_id.local_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 - ) + 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.owner, "Different parents for {:?}", item); + if dk_parent.local_id != self.parent_node { + self.parenting.insert(item, self.parent_node); } - - assert_eq!(self.parenting.insert(item, self.parent_node), None); } } -impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { +impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { type Map = Map<'hir>; /// Because we want to track parent items and so forth, enable @@ -173,26 +146,24 @@ impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { 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)); + let body = self.krate.body(id); + debug_assert_eq!(id.hir_id.owner, self.owner); + self.visit_body(body); } fn visit_param(&mut self, param: &'hir Param<'hir>) { @@ -205,8 +176,8 @@ impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { 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| { + debug_assert_eq!(i.def_id, self.owner); + self.with_parent(i.hir_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() { @@ -218,8 +189,8 @@ impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { } 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| { + debug_assert_eq!(fi.def_id, self.owner); + self.with_parent(fi.hir_id(), |this| { intravisit::walk_foreign_item(this, fi); }); } @@ -236,15 +207,15 @@ impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { } 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| { + debug_assert_eq!(ti.def_id, self.owner); + self.with_parent(ti.hir_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| { + debug_assert_eq!(ii.def_id, self.owner); + self.with_parent(ii.hir_id(), |this| { intravisit::walk_impl_item(this, ii); }); } @@ -332,7 +303,8 @@ impl<'a, 'hir: 'a> Visitor<'hir> for NodeCollector<'a, 'hir> { s: Span, id: HirId, ) { - assert_eq!(self.parent_node, id); + assert_eq!(self.owner, id.owner); + assert_eq!(self.parent_node, id.local_id); intravisit::walk_fn(self, fk, fd, b, s, id); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 89f4ec4d9f6..1a63cc1d8fe 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,5 +1,3 @@ -use self::collector::NodeCollector; - use crate::hir::{IndexedHir, ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; @@ -318,7 +316,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. @@ -1067,36 +1065,30 @@ 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 mut collector = NodeCollector::root( +pub(super) fn index_hir<'tcx>( + tcx: TyCtxt<'tcx>, + owner: LocalDefId, +) -> Option<&'tcx IndexedHir<'tcx>> { + let map = collector::collect( tcx.sess, - &**tcx.arena, tcx.untracked_crate, &tcx.untracked_resolutions.definitions, - ); - let top_mod = tcx.untracked_crate.module(); - collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID); + owner, + )?; - let map = collector.finalize_and_compute_crate_hash(); - tcx.arena.alloc(map) + Some(&*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(); - + debug_assert_eq!(crate_num, LOCAL_CRATE); 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; + .untracked_resolutions + .definitions + .def_path_table() + .all_def_path_hashes_and_def_ids() + .filter_map(|(def_path_hash, local_def_index)| { + let def_id = LocalDefId { local_def_index }; + let hash = tcx.index_hir(def_id).as_ref()?.nodes.hash; Some((def_path_hash, hash, def_id)) }) .collect(); @@ -1120,6 +1112,7 @@ 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); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 6d24190eefb..2ac64730718 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -19,16 +19,13 @@ use rustc_query_system::ich::StableHashingContext; use rustc_span::DUMMY_SP; use std::collections::BTreeMap; -/// Result of HIR indexing. -#[derive(Debug)] +/// Result of HIR indexing for a given HIR owner. +#[derive(Debug, HashStable)] 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>>, - /// 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, + /// Contents of the HIR. + nodes: OwnerNodes<'hir>, + /// Map from each nested owner to its parent's local id. + parenting: FxHashMap, } /// Top-level HIR node for current owner. This only contains the node for which @@ -132,15 +129,24 @@ pub fn provide(providers: &mut Providers) { 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 owner = tcx.index_hir(id)?; + let node = owner.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - Some(Owner { node, node_hash: owner.node_hash }) + Some(Owner { node, node_hash: owner.nodes.node_hash }) }; - providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].as_deref(); + providers.hir_owner_nodes = |tcx, id| tcx.index_hir(id).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) + 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.index_hir(parent_hir_id.owner).unwrap().parenting.get(&id) { + parent_hir_id.local_id = *local_id; + } + parent_hir_id + }); + parent }; providers.hir_attrs = |tcx, id| AttributeMap::new(&tcx.hir_crate(()).owners[id]); providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7e9391b98f7..bfded8f710a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -42,9 +42,8 @@ rustc_queries! { /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`. /// Avoid calling this query directly. - query index_hir(_: ()) -> &'tcx crate::hir::IndexedHir<'tcx> { + query index_hir(_: LocalDefId) -> Option<&'tcx crate::hir::IndexedHir<'tcx>> { eval_always - no_hash desc { "index HIR" } } -- cgit 1.4.1-3-g733a5 From 1c7f85f17c0ddde890ced0ba4445e122c1ffc093 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 12 Sep 2021 03:19:18 +0200 Subject: Perform indexing during lowering. Do not access DefId<->HirId maps before they are initialized. --- compiler/rustc_ast_lowering/src/index.rs | 361 +++++++++++++++++++++++ compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 8 +- compiler/rustc_hir/src/arena.rs | 1 + compiler/rustc_hir/src/hir.rs | 78 +++-- compiler/rustc_hir/src/intravisit.rs | 22 ++ compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_hir/src/stable_hash_impls.rs | 13 +- compiler/rustc_middle/src/arena.rs | 3 - compiler/rustc_middle/src/hir/map/collector.rs | 382 ------------------------- compiler/rustc_middle/src/hir/map/mod.rs | 29 +- compiler/rustc_middle/src/hir/mod.rs | 55 +--- compiler/rustc_middle/src/query/mod.rs | 9 +- 13 files changed, 456 insertions(+), 508 deletions(-) create mode 100644 compiler/rustc_ast_lowering/src/index.rs delete mode 100644 compiler/rustc_middle/src/hir/map/collector.rs (limited to 'compiler/rustc_middle/src/query') diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs new file mode 100644 index 00000000000..7b0f1caaee1 --- /dev/null +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -0,0 +1,361 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_hir as hir; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::definitions; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::*; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::Session; +use rustc_span::source_map::SourceMap; +use rustc_span::{Span, DUMMY_SP}; + +use std::iter::repeat; +use tracing::debug; + +/// A visitor that walks over the HIR and collects `Node`s into a HIR map. +pub(super) struct NodeCollector<'a, 'hir> { + /// Source map + source_map: &'a SourceMap, + bodies: &'a IndexVec>>, + + /// Outputs + nodes: IndexVec>>, + parenting: FxHashMap, + + /// The parent of this node + parent_node: hir::ItemLocalId, + + owner: LocalDefId, + + definitions: &'a definitions::Definitions, +} + +fn insert_vec_map(map: &mut IndexVec>, 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); +} + +pub(super) fn index_hir<'hir>( + sess: &Session, + definitions: &definitions::Definitions, + item: hir::OwnerNode<'hir>, + bodies: &IndexVec>>, +) -> (IndexVec>>, FxHashMap) { + let mut nodes = IndexVec::new(); + nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: item.into() })); + let mut collector = NodeCollector { + source_map: sess.source_map(), + definitions, + owner: item.def_id(), + parent_node: ItemLocalId::new(0), + nodes, + bodies, + parenting: FxHashMap::default(), + }; + + match item { + OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID), + OwnerNode::Item(item) => collector.visit_item(item), + OwnerNode::TraitItem(item) => collector.visit_trait_item(item), + OwnerNode::ImplItem(item) => collector.visit_impl_item(item), + OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), + }; + + (collector.nodes, collector.parenting) +} + +impl<'a, 'hir> NodeCollector<'a, 'hir> { + fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { + debug_assert_eq!(self.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.owner { + panic!( + "inconsistent DepNode at `{:?}` for `{:?}`: \ + current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", + self.source_map.span_to_diagnostic_string(span), + node, + self.definitions.def_path(self.owner).to_string_no_crate_verbose(), + self.owner, + self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(), + hir_id.owner, + ) + } + } + + insert_vec_map( + &mut self.nodes, + hir_id.local_id, + ParentedNode { parent: self.parent_node, node: node }, + ); + } + + fn with_parent(&mut self, parent_node_id: HirId, f: F) { + debug_assert_eq!(parent_node_id.owner, self.owner); + let parent_node = self.parent_node; + self.parent_node = parent_node_id.local_id; + f(self); + self.parent_node = parent_node; + } + + fn insert_nested(&mut self, item: LocalDefId) { + self.parenting.insert(item, self.parent_node); + } +} + +impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { + type Map = !; + + /// 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 { + 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); + } + + fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { + self.insert_nested(item_id.def_id); + } + + fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { + self.insert_nested(item_id.def_id); + } + + fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { + self.insert_nested(foreign_id.def_id); + } + + fn visit_nested_body(&mut self, id: BodyId) { + debug_assert_eq!(id.hir_id.owner, self.owner); + let body = self.bodies[id.hir_id.local_id].unwrap(); + self.visit_body(body); + } + + 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); + debug_assert_eq!(i.def_id, self.owner); + self.with_parent(i.hir_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>) { + debug_assert_eq!(fi.def_id, self.owner); + self.with_parent(fi.hir_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>) { + debug_assert_eq!(ti.def_id, self.owner); + self.with_parent(ti.hir_id(), |this| { + intravisit::walk_trait_item(this, ti); + }); + } + + fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { + debug_assert_eq!(ii.def_id, self.owner); + self.with_parent(ii.hir_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.owner, id.owner); + assert_eq!(self.parent_node, id.local_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_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cac5bb56c9f..d5fa52a3414 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -101,7 +101,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let old_len = self.in_scope_lifetimes.len(); let parent_generics = - match self.owners[parent_hir_id].as_ref().unwrap().node.expect_item().kind { + match self.owners[parent_hir_id].as_ref().unwrap().node().expect_item().kind { hir::ItemKind::Impl(hir::Impl { ref generics, .. }) | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, _ => &[], diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f95ad9f3a9b..a7f1ba8b791 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -33,6 +33,7 @@ #![feature(crate_visibility_modifier)] #![feature(box_patterns)] #![feature(iter_zip)] +#![feature(never_type)] #![recursion_limit = "256"] use rustc_ast::token::{self, Token}; @@ -78,6 +79,7 @@ macro_rules! arena_vec { mod asm; mod block; mod expr; +mod index; mod item; mod pat; mod path; @@ -434,6 +436,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.local_node_ids.push(owner); let item = f(self); + debug_assert_eq!(def_id, item.def_id()); let info = self.make_owner_info(item); self.attrs = current_attrs; @@ -470,8 +473,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let (hash, node_hash) = self.hash_body(node, &bodies); + let (nodes, parenting) = + index::index_hir(self.sess, self.resolver.definitions(), node, &bodies); + let nodes = hir::OwnerNodes { hash, node_hash, nodes, bodies }; - hir::OwnerInfo { hash, node_hash, node, attrs, bodies, trait_map } + hir::OwnerInfo { nodes, parenting, attrs, trait_map } } /// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index 5334f6d729d..1a34dd04428 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -37,6 +37,7 @@ macro_rules! arena_types { [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, [] local: rustc_hir::Local<$tcx>, [few] mod_: rustc_hir::Mod<$tcx>, + [] owner_info: rustc_hir::OwnerInfo<$tcx>, [] param: rustc_hir::Param<$tcx>, [] pat: rustc_hir::Pat<$tcx>, [] path: rustc_hir::Path<$tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 44652d0198f..4c8157fee37 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,5 +1,5 @@ use crate::def::{CtorKind, DefKind, Res}; -use crate::def_id::{DefId, CRATE_DEF_ID}; +use crate::def_id::DefId; crate use crate::hir_id::{HirId, ItemLocalId}; use crate::LangItem; @@ -663,18 +663,49 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } +/// 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> { + pub parent: ItemLocalId, + pub node: Node<'tcx>, +} + +#[derive(Debug)] +pub struct OwnerNodes<'tcx> { + /// Pre-computed hash of the full HIR. + pub hash: Fingerprint, + /// Pre-computed hash of the top node. + pub node_hash: Fingerprint, + /// Full HIR for the current owner. + // The zeroth node's parent is trash, but is never accessed. + pub nodes: IndexVec>>, + /// Content of local bodies. + pub bodies: IndexVec>>, +} + #[derive(Debug)] pub struct OwnerInfo<'hir> { - pub node: OwnerNode<'hir>, + /// Contents of the HIR. + pub nodes: OwnerNodes<'hir>, + /// Map from each nested owner to its parent's local id. + pub parenting: FxHashMap, + pub attrs: BTreeMap, - pub bodies: IndexVec>>, /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap>, - /// Pre-computed hash of the full HIR. - pub hash: Fingerprint, - /// Pre-computed hash of the top node. - pub node_hash: Fingerprint, +} + +impl<'tcx> OwnerInfo<'tcx> { + #[inline] + pub fn node(&self) -> OwnerNode<'tcx> { + use rustc_index::vec::Idx; + let node = self.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; + let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. + node + } } /// The top-level data structure that stores the entire contents of @@ -688,39 +719,6 @@ pub struct Crate<'hir> { pub owners: IndexVec>>, } -impl Crate<'hir> { - pub fn module(&self) -> &'hir Mod<'hir> { - let i = self.owners[CRATE_DEF_ID].as_ref().unwrap().node; - if let OwnerNode::Crate(m) = i { m } else { panic!() } - } - - pub fn item(&self, id: ItemId) -> &'hir Item<'hir> { - self.owners[id.def_id].as_ref().unwrap().node.expect_item() - } - - pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().node.expect_trait_item() - } - - pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().node.expect_impl_item() - } - - pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.owners[id.def_id].as_ref().unwrap().node.expect_foreign_item() - } - - pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - let HirId { owner, local_id } = id.hir_id; - self.owners[owner].as_ref().unwrap().bodies[local_id].unwrap() - } - - pub fn attrs(&self, id: HirId) -> &'hir [Attribute] { - let HirId { owner, local_id } = id; - &self.owners[owner].as_ref().unwrap().attrs.get(&local_id).map(|la| *la).unwrap_or(&[]) - } -} - /// A block of statements `{ .. }`, which may have a label (in this case the /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1ac2625dd47..3e58af1f167 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -130,6 +130,28 @@ pub trait Map<'hir> { fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>; } +// Used when no map is actually available, forcing manual implementation of nested visitors. +impl Map<'hir> for ! { + fn find(&self, _: HirId) -> Option> { + unreachable!() + } + fn body(&self, _: BodyId) -> &'hir Body<'hir> { + unreachable!() + } + fn item(&self, _: ItemId) -> &'hir Item<'hir> { + unreachable!() + } + fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> { + unreachable!() + } + fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> { + unreachable!() + } + fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> { + unreachable!() + } +} + /// An erased version of `Map<'hir>`, using dynamic dispatch. /// NOTE: This type is effectively only usable with `NestedVisitorMap::None`. pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>); diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index f5ea044e248..af8421aeb89 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -6,6 +6,7 @@ #![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] +#![feature(never_type)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 9d5ef279dd7..ad73e363d7f 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, - TraitItemId, Ty, VisibilityKind, + BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, OwnerNodes, + TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -209,3 +209,12 @@ impl HashStable for Item<'_> { }); } } + +impl HashStable for OwnerNodes<'tcx> { + fn hash_stable(&self, hcx: &mut HirCtx, 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, node_hash: _, nodes: _, bodies: _ } = *self; + hash.hash_stable(hcx, hasher); + } +} diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 2986e8c7a06..4a027cb7ebe 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -92,9 +92,6 @@ macro_rules! arena_types { [] tys: rustc_middle::ty::TyS<$tcx>, [] predicates: rustc_middle::ty::PredicateInner<$tcx>, - // HIR query types - [] indexed_hir: rustc_middle::hir::IndexedHir<$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 a9e676b9e30..00000000000 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ /dev/null @@ -1,382 +0,0 @@ -use crate::hir::map::Map; -use crate::hir::{IndexedHir, OwnerNodes, ParentedNode}; -use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::definitions; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::*; -use rustc_index::vec::{Idx, IndexVec}; -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> { - /// The crate - krate: &'hir Crate<'hir>, - - /// Source map - source_map: &'a SourceMap, - - nodes: OwnerNodes<'hir>, - parenting: FxHashMap, - - /// The parent of this node - parent_node: hir::ItemLocalId, - - owner: LocalDefId, - - definitions: &'a definitions::Definitions, -} - -fn insert_vec_map(map: &mut IndexVec>, 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); -} - -pub(super) fn collect<'a, 'hir: 'a>( - sess: &'a Session, - krate: &'hir Crate<'hir>, - definitions: &'a definitions::Definitions, - owner: LocalDefId, -) -> Option> { - let info = krate.owners.get(owner)?.as_ref()?; - let item = info.node; - let mut nodes = IndexVec::new(); - nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: item.into() })); - let mut collector = NodeCollector { - krate, - source_map: sess.source_map(), - owner, - parent_node: ItemLocalId::new(0), - definitions, - nodes: OwnerNodes { - hash: info.hash, - node_hash: info.node_hash, - nodes, - bodies: &info.bodies, - }, - parenting: FxHashMap::default(), - }; - - match item { - OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID), - OwnerNode::Item(item) => collector.visit_item(item), - OwnerNode::TraitItem(item) => collector.visit_trait_item(item), - OwnerNode::ImplItem(item) => collector.visit_impl_item(item), - OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), - }; - - Some(IndexedHir { nodes: collector.nodes, parenting: collector.parenting }) -} - -impl<'a, 'hir> NodeCollector<'a, 'hir> { - fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { - debug_assert_eq!(self.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.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.owner).to_string_no_crate_verbose(), - self.owner, - self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(), - hir_id.owner, - ) - } - } - - insert_vec_map( - &mut self.nodes.nodes, - hir_id.local_id, - ParentedNode { parent: self.parent_node, node: node }, - ); - } - - fn with_parent(&mut self, parent_node_id: HirId, f: F) { - debug_assert_eq!(parent_node_id.owner, self.owner); - let parent_node = self.parent_node; - self.parent_node = parent_node_id.local_id; - f(self); - self.parent_node = parent_node; - } - - fn insert_nested(&mut self, item: LocalDefId) { - 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.owner, "Different parents for {:?}", item); - if dk_parent.local_id != self.parent_node { - self.parenting.insert(item, self.parent_node); - } - } -} - -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 { - 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); - } - - fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - self.insert_nested(item_id.def_id); - } - - fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - self.insert_nested(item_id.def_id); - } - - fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { - self.insert_nested(foreign_id.def_id); - } - - fn visit_nested_body(&mut self, id: BodyId) { - let body = self.krate.body(id); - debug_assert_eq!(id.hir_id.owner, self.owner); - self.visit_body(body); - } - - 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); - debug_assert_eq!(i.def_id, self.owner); - self.with_parent(i.hir_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>) { - debug_assert_eq!(fi.def_id, self.owner); - self.with_parent(fi.hir_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>) { - debug_assert_eq!(ti.def_id, self.owner); - self.with_parent(ti.hir_id(), |this| { - intravisit::walk_trait_item(this, ti); - }); - } - - fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { - debug_assert_eq!(ii.def_id, self.owner); - self.with_parent(ii.hir_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.owner, id.owner); - assert_eq!(self.parent_node, id.local_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 1a63cc1d8fe..834d5f964e1 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,4 +1,4 @@ -use crate::hir::{IndexedHir, ModuleItems, Owner}; +use crate::hir::{ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; @@ -21,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 { @@ -164,7 +163,7 @@ impl<'hir> Map<'hir> { pub fn items(&self) -> impl Iterator> + 'hir { let krate = self.krate(); - krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node { + krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node() { OwnerNode::Item(item) => Some(item), _ => None, }) @@ -497,7 +496,7 @@ impl<'hir> Map<'hir> { .owners .iter_enumerated() .flat_map(move |(owner, owner_info)| { - let bodies = &owner_info.as_ref()?.bodies; + let bodies = &owner_info.as_ref()?.nodes.bodies; Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| { if body.is_none() { return None; @@ -518,7 +517,7 @@ impl<'hir> Map<'hir> { 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.raw).enumerate().for_each(|(local_id, body)| { + 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 }; @@ -605,7 +604,7 @@ impl<'hir> Map<'hir> { { let krate = self.krate(); for owner in krate.owners.iter().filter_map(Option::as_ref) { - match owner.node { + 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), @@ -621,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().map(|o| o.node) { + 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), @@ -1065,20 +1064,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub(super) fn index_hir<'tcx>( - tcx: TyCtxt<'tcx>, - owner: LocalDefId, -) -> Option<&'tcx IndexedHir<'tcx>> { - let map = collector::collect( - tcx.sess, - tcx.untracked_crate, - &tcx.untracked_resolutions.definitions, - owner, - )?; - - Some(&*tcx.arena.alloc(map)) -} - pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { debug_assert_eq!(crate_num, LOCAL_CRATE); let mut hir_body_nodes: Vec<_> = tcx @@ -1088,7 +1073,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { .all_def_path_hashes_and_def_ids() .filter_map(|(def_path_hash, local_def_index)| { let def_id = LocalDefId { local_def_index }; - let hash = tcx.index_hir(def_id).as_ref()?.nodes.hash; + let hash = tcx.hir_crate(()).owners[def_id].as_ref()?.nodes.hash; Some((def_path_hash, hash, def_id)) }) .collect(); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 2ac64730718..70179e73b19 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -10,24 +10,13 @@ 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 for a given HIR owner. -#[derive(Debug, HashStable)] -pub struct IndexedHir<'hir> { - /// Contents of the HIR. - nodes: OwnerNodes<'hir>, - /// Map from each nested owner to its parent's local id. - parenting: FxHashMap, -} - /// Top-level HIR node for current owner. This only contains the node for which /// `HirId::local_id == 0`, and excludes bodies. /// @@ -47,38 +36,6 @@ impl<'a, 'tcx> HashStable> for Owner<'tcx> { } } -/// 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, - /// Pre-computed hash of the top node. - node_hash: Fingerprint, - /// Full HIR for the current owner. - // The zeroth node's parent is trash, but is never accessed. - nodes: IndexVec>>, - /// Content of local bodies. - bodies: &'tcx IndexVec>>, -} - -impl<'a, 'tcx> HashStable> for OwnerNodes<'tcx> { - #[inline] - 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, node_hash: _, nodes: _, bodies: _ } = *self; - hash.hash_stable(hcx, hasher); - } -} - /// Attributes owner by a HIR owner. #[derive(Copy, Clone, Debug, HashStable)] pub struct AttributeMap<'tcx> { @@ -125,23 +82,23 @@ 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(id)?; - let node = owner.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. + let owner = tcx.hir_crate(()).owners[id].as_ref()?; + let node = owner.node(); Some(Owner { node, node_hash: owner.nodes.node_hash }) }; - providers.hir_owner_nodes = |tcx, id| tcx.index_hir(id).map(|i| &i.nodes); + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { 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.index_hir(parent_hir_id.owner).unwrap().parenting.get(&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 diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bfded8f710a..e604f59175e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -40,13 +40,6 @@ rustc_queries! { desc { "get the crate HIR" } } - /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`. - /// Avoid calling this query directly. - query index_hir(_: LocalDefId) -> Option<&'tcx crate::hir::IndexedHir<'tcx>> { - eval_always - desc { "index HIR" } - } - /// The items in a module. /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. @@ -76,7 +69,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>> { + 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()) } } -- cgit 1.4.1-3-g733a5 From 41e80b85cf05e6373b589b876d3ee65823196406 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 12 Sep 2021 11:41:35 +0200 Subject: Directly use AttributeMap inside OwnerInfo. --- compiler/rustc_ast_lowering/src/lib.rs | 7 +++++++ compiler/rustc_hir/src/hir.rs | 21 +++++++++++++++++++-- compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_hir/src/stable_hash_impls.rs | 13 +++++++++++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 23 ++--------------------- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 2 +- 8 files changed, 42 insertions(+), 28 deletions(-) (limited to 'compiler/rustc_middle/src/query') diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a7f1ba8b791..9ba3d0446dd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -476,6 +476,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (nodes, parenting) = index::index_hir(self.sess, self.resolver.definitions(), node, &bodies); let nodes = hir::OwnerNodes { hash, node_hash, nodes, bodies }; + let attrs = { + let mut hcx = self.resolver.create_stable_hashing_context(); + let mut stable_hasher = StableHasher::new(); + attrs.hash_stable(&mut hcx, &mut stable_hasher); + let hash = stable_hasher.finish(); + hir::AttributeMap { map: attrs, hash } + }; hir::OwnerInfo { nodes, parenting, attrs, trait_map } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c8157fee37..bb5c0bc1889 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -672,6 +672,23 @@ pub struct ParentedNode<'tcx> { pub node: Node<'tcx>, } +/// Attributes owner by a HIR owner. +#[derive(Debug)] +pub struct AttributeMap<'tcx> { + pub map: BTreeMap, + pub hash: Fingerprint, +} + +impl<'tcx> AttributeMap<'tcx> { + pub const EMPTY: &'static AttributeMap<'static> = + &AttributeMap { map: BTreeMap::new(), hash: Fingerprint::ZERO }; + + #[inline] + pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { + self.map.get(&id).copied().unwrap_or(&[]) + } +} + #[derive(Debug)] pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. @@ -691,8 +708,8 @@ pub struct OwnerInfo<'hir> { pub nodes: OwnerNodes<'hir>, /// Map from each nested owner to its parent's local id. pub parenting: FxHashMap, - - pub attrs: BTreeMap, + /// Collected attributes of the HIR nodes. + pub attrs: AttributeMap<'hir>, /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap>, diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index af8421aeb89..93224d388c0 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -2,6 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html +#![feature(const_btree_new)] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] #![feature(once_cell)] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index ad73e363d7f..da2aeb9b311 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, OwnerNodes, - TraitItem, TraitItemId, Ty, VisibilityKind, + AttributeMap, BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, + Mod, OwnerNodes, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -218,3 +218,12 @@ impl HashStable for OwnerNodes<'tcx> { hash.hash_stable(hcx, hasher); } } + +impl HashStable for AttributeMap<'tcx> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + // We ignore the `map` since it refers to information included in `hash` which is hashed in + // the collector and used for the crate hash. + let AttributeMap { hash, map: _ } = *self; + hash.hash_stable(hcx, hasher); + } +} diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 834d5f964e1..af4c0e4843d 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -580,7 +580,7 @@ impl<'hir> Map<'hir> { let krate = self.krate(); for (owner, info) in krate.owners.iter_enumerated() { if let Some(info) = info { - for (&local_id, attrs) in info.attrs.iter() { + for (&local_id, attrs) in info.attrs.map.iter() { let id = HirId { owner, local_id }; for a in *attrs { visitor.visit_attribute(id, a) diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 70179e73b19..f941981be79 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -8,14 +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::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::LocalDefId; use rustc_hir::*; use rustc_query_system::ich::StableHashingContext; use rustc_span::DUMMY_SP; -use std::collections::BTreeMap; /// Top-level HIR node for current owner. This only contains the node for which /// `HirId::local_id == 0`, and excludes bodies. @@ -36,24 +34,6 @@ impl<'a, 'tcx> HashStable> for Owner<'tcx> { } } -/// Attributes owner by a HIR owner. -#[derive(Copy, Clone, Debug, HashStable)] -pub struct AttributeMap<'tcx> { - map: &'tcx BTreeMap, -} - -impl<'tcx> AttributeMap<'tcx> { - fn new(owner_info: &'tcx Option>) -> AttributeMap<'tcx> { - const FALLBACK: &'static BTreeMap = &BTreeMap::new(); - let map = owner_info.as_ref().map_or(FALLBACK, |info| &info.attrs); - AttributeMap { map } - } - - fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] { - self.map.get(&id).copied().unwrap_or(&[]) - } -} - /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. #[derive(Debug, HashStable)] @@ -105,7 +85,8 @@ pub fn provide(providers: &mut Providers) { }); parent }; - providers.hir_attrs = |tcx, id| AttributeMap::new(&tcx.hir_crate(()).owners[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 e7219cc58a1..e41f5add457 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,7 +30,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(core_intrinsics)] -#![feature(const_btree_new)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e604f59175e..eb4cc7c750c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -77,7 +77,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> { + query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) } } -- cgit 1.4.1-3-g733a5 From 0431fdb11312ae324c73e4dab1e5be5c45164678 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 19 Sep 2021 22:07:12 +0200 Subject: Compute full HIR hash during lowering. --- compiler/rustc_ast_lowering/src/lib.rs | 23 +++++++++++- compiler/rustc_hir/src/hir.rs | 3 +- compiler/rustc_hir/src/stable_hash_impls.rs | 18 ++++++++-- compiler/rustc_middle/src/hir/map/mod.rs | 45 ++++++++++-------------- compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_query_system/src/ich/impls_hir.rs | 36 ++++++------------- 6 files changed, 69 insertions(+), 57 deletions(-) (limited to 'compiler/rustc_middle/src/query') diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9ba3d0446dd..84aeb78a0aa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -399,6 +399,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Crate(lctx.arena.alloc(module)) }); + let hir_hash = self.compute_hir_hash(); + let mut def_id_to_hir_id = IndexVec::default(); for (node_id, hir_id) in self.node_id_to_hir_id.into_iter_enumerated() { @@ -412,10 +414,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.definitions().init_def_id_to_hir_id_mapping(def_id_to_hir_id); - let krate = hir::Crate { owners: self.owners }; + let krate = hir::Crate { owners: self.owners, hir_hash }; self.arena.alloc(krate) } + fn compute_hir_hash(&mut self) -> Fingerprint { + let definitions = self.resolver.definitions(); + let mut hir_body_nodes: Vec<_> = self + .owners + .iter_enumerated() + .filter_map(|(def_id, info)| { + let info = info.as_ref()?; + let def_path_hash = definitions.def_path_hash(def_id); + Some((def_path_hash, info)) + }) + .collect(); + hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + + let mut stable_hasher = StableHasher::new(); + let mut hcx = self.resolver.create_stable_hashing_context(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() + } + fn with_hir_id_owner( &mut self, owner: NodeId, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bb5c0bc1889..6cbea732c99 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -702,7 +702,7 @@ pub struct OwnerNodes<'tcx> { pub bodies: IndexVec>>, } -#[derive(Debug)] +#[derive(Debug, HashStable_Generic)] pub struct OwnerInfo<'hir> { /// Contents of the HIR. pub nodes: OwnerNodes<'hir>, @@ -734,6 +734,7 @@ impl<'tcx> OwnerInfo<'tcx> { #[derive(Debug)] pub struct Crate<'hir> { pub owners: IndexVec>>, + pub hir_hash: Fingerprint, } /// A block of statements `{ .. }`, which may have a label (in this case the diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index da2aeb9b311..3c9fe93b67d 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,8 +1,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ - AttributeMap, BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, - Mod, OwnerNodes, TraitItem, TraitItemId, Ty, VisibilityKind, + AttributeMap, BodyId, Crate, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, + ItemId, Mod, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -21,6 +21,7 @@ pub trait HashStableContext: fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); fn hash_hir_item_like(&mut self, f: F); + fn hash_hir_trait_candidate(&mut self, _: &TraitCandidate, hasher: &mut StableHasher); } impl ToStableHashKey for HirId { @@ -227,3 +228,16 @@ impl HashStable for AttributeMap<'tcx> hash.hash_stable(hcx, hasher); } } + +impl HashStable for Crate<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let Crate { owners: _, hir_hash } = self; + hir_hash.hash_stable(hcx, hasher) + } +} + +impl HashStable for TraitCandidate { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + hcx.hash_hir_trait_candidate(self, hasher) + } +} diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index af4c0e4843d..c8d6ecf6940 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1066,18 +1066,8 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { debug_assert_eq!(crate_num, LOCAL_CRATE); - let mut hir_body_nodes: Vec<_> = tcx - .untracked_resolutions - .definitions - .def_path_table() - .all_def_path_hashes_and_def_ids() - .filter_map(|(def_path_hash, local_def_index)| { - let def_id = LocalDefId { local_def_index }; - let hash = tcx.hir_crate(()).owners[def_id].as_ref()?.nodes.hash; - Some((def_path_hash, hash, def_id)) - }) - .collect(); - hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + let krate = tcx.hir_crate(()); + let hir_body_hash = krate.hir_hash; let upstream_crates = upstream_crates(tcx); @@ -1099,22 +1089,25 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { 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); - 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); - 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/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index eb4cc7c750c..4ffe76fed1c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -36,7 +36,6 @@ 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" } } diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs index dc208b36f93..24f3a2e7de0 100644 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -6,8 +6,6 @@ use crate::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::definitions::DefPathHash; -use smallvec::SmallVec; use std::mem; impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { @@ -121,6 +119,16 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { self.node_id_hashing_mode = prev_hash_node_ids; } + + #[inline] + fn hash_hir_trait_candidate(&mut self, tc: &hir::TraitCandidate, hasher: &mut StableHasher) { + self.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + let hir::TraitCandidate { def_id, import_ids } = tc; + + def_id.hash_stable(hcx, hasher); + import_ids.hash_stable(hcx, hasher); + }); + } } impl<'a> HashStable> for hir::Body<'_> { @@ -135,27 +143,3 @@ impl<'a> HashStable> for hir::Body<'_> { }); } } - -impl<'a> HashStable> for hir::TraitCandidate { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - let hir::TraitCandidate { def_id, import_ids } = self; - - def_id.hash_stable(hcx, hasher); - import_ids.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> ToStableHashKey> for hir::TraitCandidate { - type KeyType = (DefPathHash, SmallVec<[DefPathHash; 1]>); - - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Self::KeyType { - let hir::TraitCandidate { def_id, import_ids } = self; - - ( - hcx.def_path_hash(*def_id), - import_ids.iter().map(|def_id| hcx.local_def_path_hash(*def_id)).collect(), - ) - } -} -- cgit 1.4.1-3-g733a5