diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index dd242686d26f2..4fc93ed9f8f8b 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -159,6 +159,12 @@ macro_rules! arena_types { [] type_binding: rustc_hir::TypeBinding<$tcx>, [] variant: rustc_hir::Variant<$tcx>, [] where_predicate: rustc_hir::WherePredicate<$tcx>, + + // HIR query types + [few] hir_map: rustc::hir::map::Map<$tcx>, + [few] hir_definitions: rustc::hir::map::definitions::Definitions, + [] hir_owner: rustc::hir::HirOwner<$tcx>, + [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>, ], $tcx); ) } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 29b94986a5f3a..35e5616fc6709 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -35,7 +35,7 @@ //! "infer" some properties for each kind of `DepNode`: //! //! * Whether a `DepNode` of a given kind has any parameters at all. Some -//! `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value. +//! `DepNode`s, like `?`, represent global concepts with only one value. //! * Whether it is possible, in principle, to reconstruct a query key from a //! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, //! in which case it is possible to map the node's fingerprint back to the @@ -276,8 +276,8 @@ macro_rules! define_dep_nodes { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(kind: DepKind, - def_path_hash: DefPathHash) + pub fn from_def_path_hash(def_path_hash: DefPathHash, + kind: DepKind) -> DepNode { debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); DepNode { @@ -333,7 +333,7 @@ macro_rules! define_dep_nodes { } if kind.has_params() { - Ok(def_path_hash.to_dep_node(kind)) + Ok(DepNode::from_def_path_hash(def_path_hash, kind)) } else { Ok(DepNode::new_no_params(kind)) } @@ -390,28 +390,13 @@ impl fmt::Debug for DepNode { } } -impl DefPathHash { - pub fn to_dep_node(self, kind: DepKind) -> DepNode { - DepNode::from_def_path_hash(kind, self) - } -} - rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, - // Represents the body of a function or method. The def-id is that of the - // function/method. - [eval_always] HirBody(DefId), - - // Represents the HIR node with the given node-id - [eval_always] Hir(DefId), - // Represents metadata from an extern crate. [eval_always] CrateMetadata(CrateNum), - [eval_always] AllLocalTraitImpls, - [anon] TraitSelect, [] CompileCodegenUnit(Symbol), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 258723bb39d83..4a50ec2d99aca 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -677,7 +677,7 @@ impl DepGraph { } } else { match dep_dep_node.kind { - DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { + DepKind::CrateMetadata => { if let Some(def_id) = dep_dep_node.extract_def_id(tcx) { if def_id_corresponds_to_hir_dep_node(tcx, def_id) { // The `DefPath` has corresponding node, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 4c922654e02d5..109804db46a22 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,6 +1,7 @@ -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::arena::Arena; use crate::hir::map::definitions::{self, DefPathHash}; -use crate::hir::map::{Entry, HirEntryMap, Map}; +use crate::hir::map::{Entry, Map}; +use crate::hir::{HirItem, HirOwner, HirOwnerItems}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; use rustc_data_structures::fingerprint::Fingerprint; @@ -22,76 +23,49 @@ 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, - /// The node map - map: HirEntryMap<'hir>, + owner_map: FxHashMap>, + owner_items_map: FxHashMap>, + /// The parent of this node parent_node: hir::HirId, - // These fields keep track of the currently relevant DepNodes during - // the visitor's traversal. current_dep_node_owner: DefIndex, - current_signature_dep_index: DepNodeIndex, - current_full_dep_index: DepNodeIndex, - currently_in_body: bool, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, hir_to_node_id: &'a FxHashMap, hcx: StableHashingContext<'a>, - // We are collecting `DepNode::HirBody` hashes here so we can compute the - // crate hash from then later on. + // We are collecting HIR hashes here so we can compute the + // crate hash from them later on. hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } -fn input_dep_node_and_hash( - dep_graph: &DepGraph, +fn hash( hcx: &mut StableHashingContext<'_>, - dep_node: DepNode, input: impl for<'a> HashStable>, -) -> (DepNodeIndex, Fingerprint) { - let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; - - let hash = if dep_graph.is_fully_enabled() { - dep_graph.fingerprint_of(dep_node_index) - } else { - let mut stable_hasher = StableHasher::new(); - input.hash_stable(hcx, &mut stable_hasher); - stable_hasher.finish() - }; - - (dep_node_index, hash) +) -> Fingerprint { + let mut stable_hasher = StableHasher::new(); + input.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() } -fn alloc_hir_dep_nodes( - dep_graph: &DepGraph, +fn hash_body( hcx: &mut StableHashingContext<'_>, def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, -) -> (DepNodeIndex, DepNodeIndex) { - let sig = dep_graph - .input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, - ) - .1; - let (full, hash) = input_dep_node_and_hash( - dep_graph, - hcx, - def_path_hash.to_dep_node(DepKind::HirBody), - HirItemLike { item_like: &item_like, hash_bodies: true }, - ); +) { + let hash = hash(hcx, HirItemLike { item_like: &item_like }); hir_body_nodes.push((def_path_hash, hash)); - (sig, full) } fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { @@ -112,8 +86,8 @@ fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root( sess: &'a Session, + arena: &'hir Arena<'hir>, krate: &'hir Crate<'hir>, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, hir_to_node_id: &'a FxHashMap, mut hcx: StableHashingContext<'a>, @@ -122,14 +96,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let mut hir_body_nodes = Vec::new(); - // Allocate `DepNode`s for the root module. - let (root_mod_sig_dep_index, root_mod_full_dep_index) = { + { let Crate { - ref module, - // Crate attributes are not copied over to the root `Mod`, so hash - // them explicitly here. - ref attrs, - span, + ref item, // These fields are handled separately: exported_macros: _, non_exported_macro_attrs: _, @@ -142,45 +111,31 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { modules: _, } = *krate; - alloc_hir_dep_nodes( - dep_graph, - &mut hcx, - root_mod_def_path_hash, - (module, attrs, span), - &mut hir_body_nodes, - ) + hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) }; - { - dep_graph.input_task( - DepNode::new_no_params(DepKind::AllLocalTraitImpls), - &mut hcx, - &krate.trait_impls, - ); - } - let mut collector = NodeCollector { + arena, krate, source_map: sess.source_map(), - map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()), parent_node: hir::CRATE_HIR_ID, - current_signature_dep_index: root_mod_sig_dep_index, - current_full_dep_index: root_mod_full_dep_index, current_dep_node_owner: CRATE_DEF_INDEX, - currently_in_body: false, - dep_graph, definitions, hir_to_node_id, hcx, hir_body_nodes, + owner_map: FxHashMap::with_capacity_and_hasher( + definitions.def_index_count(), + Default::default(), + ), + owner_items_map: FxHashMap::with_capacity_and_hasher( + definitions.def_index_count(), + Default::default(), + ), }; collector.insert_entry( hir::CRATE_HIR_ID, - Entry { - parent: hir::CRATE_HIR_ID, - dep_node: root_mod_sig_dep_index, - node: Node::Crate, - }, + Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) }, ); collector @@ -191,7 +146,17 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64, - ) -> (HirEntryMap<'hir>, Svh) { + ) -> ( + FxHashMap>, + FxHashMap>, + Svh, + ) { + // Insert bodies into the map + for (id, body) in self.krate.bodies.iter() { + let bodies = &mut self.owner_items_map.get_mut(&id.hir_id.owner).unwrap().bodies; + assert!(bodies.insert(id.hir_id.local_id, body).is_none()); + } + self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); let node_hashes = self.hir_body_nodes.iter().fold( @@ -228,30 +193,37 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash: Fingerprint = stable_hasher.finish(); let svh = Svh::new(crate_hash.to_smaller_hash()); - (self.map, svh) + (self.owner_map, self.owner_items_map, svh) } fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { - debug!("hir_map: {:?} => {:?}", id, entry); - let local_map = &mut self.map[id.owner]; let i = id.local_id.as_u32() as usize; - let len = local_map.len(); - if i >= len { - local_map.extend(repeat(None).take(i - len + 1)); + + let owner = HirOwner { parent: entry.parent, node: entry.node }; + + let arena = self.arena; + + let items = self.owner_items_map.entry(id.owner).or_insert_with(|| { + arena.alloc(HirOwnerItems { items: IndexVec::new(), bodies: FxHashMap::default() }) + }); + + if i == 0 { + self.owner_map.insert(id.owner, self.arena.alloc(owner)); + // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert + //assert!(self.owner_map.insert(id.owner, self.arena.alloc(owner)).is_none()); + } else { + let len = items.items.len(); + if i >= len { + items.items.extend(repeat(None).take(i - len + 1)); + } + assert_eq!(entry.parent.owner, id.owner); + items.items[id.local_id] = + Some(HirItem { parent: entry.parent.local_id, node: entry.node }); } - local_map[id.local_id] = Some(entry); } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { - let entry = Entry { - parent: self.parent_node, - dep_node: if self.currently_in_body { - self.current_full_dep_index - } else { - self.current_signature_dep_index - }, - node, - }; + let entry = Entry { parent: self.parent_node, node }; // Make sure that the DepNode of some node coincides with the HirId // owner of that node. @@ -306,29 +278,14 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { f: F, ) { let prev_owner = self.current_dep_node_owner; - let prev_signature_dep_index = self.current_signature_dep_index; - let prev_full_dep_index = self.current_full_dep_index; - let prev_in_body = self.currently_in_body; let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes( - self.dep_graph, - &mut self.hcx, - def_path_hash, - item_like, - &mut self.hir_body_nodes, - ); - self.current_signature_dep_index = signature_dep_index; - self.current_full_dep_index = full_dep_index; + hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); self.current_dep_node_owner = dep_node_owner; - self.currently_in_body = false; f(self); - self.currently_in_body = prev_in_body; self.current_dep_node_owner = prev_owner; - self.current_full_dep_index = prev_full_dep_index; - self.current_signature_dep_index = prev_signature_dep_index; } } @@ -357,10 +314,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_nested_body(&mut self, id: BodyId) { - let prev_in_body = self.currently_in_body; - self.currently_in_body = true; self.visit_body(self.krate.body(id)); - self.currently_in_body = prev_in_body; } fn visit_param(&mut self, param: &'hir Param<'hir>) { @@ -583,11 +537,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } -// This is a wrapper structure that allows determining if span values within -// the wrapped item should be hashed or not. struct HirItemLike { item_like: T, - hash_bodies: bool, } impl<'hir, T> HashStable> for HirItemLike @@ -595,7 +546,7 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| { + hcx.while_hashing_hir_bodies(true, |hcx| { self.item_like.hash_stable(hcx, hasher); }); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 048c1f026be82..904cfa8fca3e1 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -4,7 +4,6 @@ //! There are also some rather random cases (like const initializer //! expressions) that are mostly just leftovers. -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_hir as hir; @@ -17,10 +16,11 @@ use rustc_span::Span; use syntax::ast; use syntax::node_id::NodeMap; -use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; +pub use rustc_hir::def_id::DefPathHash; + /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` /// stores the `DefIndex` of its parent. @@ -282,28 +282,6 @@ pub enum DefPathData { ImplTrait, } -#[derive( - Copy, - Clone, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] -pub struct DefPathHash(pub Fingerprint); - -impl Borrow for DefPathHash { - #[inline] - fn borrow(&self) -> &Fingerprint { - &self.0 - } -} - impl Definitions { pub fn def_path_table(&self) -> &DefPathTable { &self.table diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index c721faafbecaf..0a04fef9da577 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,14 +1,14 @@ -use crate::hir::map::Map; -use rustc_data_structures::fx::FxHashSet; +use crate::hir::map::EarlyMap; +/*use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{HirId, ItemLocalId};*/ -pub fn check_crate(hir_map: &Map<'_>) { - hir_map.dep_graph.assert_ignored(); +pub fn check_crate(_: &EarlyMap<'_>) { + /*hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); @@ -25,23 +25,23 @@ pub fn check_crate(hir_map: &Map<'_>) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); bug!("{}", message); - } + }*/ } - +/* struct HirIdValidator<'a, 'hir> { - hir_map: &'a Map<'hir>, + hir_map: &'a EarlyMap<'hir>, owner_def_index: Option, hir_ids_seen: FxHashSet, errors: &'a Lock>, } struct OuterVisitor<'a, 'hir> { - hir_map: &'a Map<'hir>, + hir_map: &'a EarlyMap<'hir>, errors: &'a Lock>, } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: &'a EarlyMap<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, owner_def_index: None, @@ -133,7 +133,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - type Map = Map<'hir>; + type Map = EarlyMap<'hir>; fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, Self::Map> { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) @@ -173,3 +173,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { // different owner. } } +*/ diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1645420892a75..9d200b5410985 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -3,18 +3,19 @@ pub use self::definitions::{ DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, }; -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::arena::Arena; +use crate::hir::{HirOwner, HirOwnerItems}; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; +use crate::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; use rustc_hir::*; -use rustc_index::vec::IndexVec; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::kw; @@ -31,126 +32,135 @@ mod hir_id_validator; #[derive(Copy, Clone, Debug)] pub struct Entry<'hir> { parent: HirId, - dep_node: DepNodeIndex, node: Node<'hir>, } impl<'hir> Entry<'hir> { fn parent_node(self) -> Option { match self.node { - Node::Crate | Node::MacroDef(_) => None, + Node::Crate(_) | Node::MacroDef(_) => None, _ => Some(self.parent), } } +} - fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { - match self.node { - Node::Item(ref item) => match item.kind { - ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), - _ => None, - }, - - Node::TraitItem(ref item) => match item.kind { - TraitItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None, - }, +fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { + match node { + Node::Item(ref item) => match item.kind { + ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), + _ => None, + }, - Node::ImplItem(ref item) => match item.kind { - ImplItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None, - }, + Node::TraitItem(ref item) => match item.kind { + TraitItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::Expr(ref expr) => match expr.kind { - ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), - _ => None, - }, + Node::ImplItem(ref item) => match item.kind { + ImplItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, + Node::Expr(ref expr) => match expr.kind { + ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), _ => None, - } - } + }, - fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { - match &self.node { - Node::Item(item) => match &item.kind { - ItemKind::Fn(sig, _, _) => Some(sig), - _ => None, - }, + _ => None, + } +} - Node::TraitItem(item) => match &item.kind { - TraitItemKind::Method(sig, _) => Some(sig), - _ => None, - }, +fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> { + match &node { + Node::Item(item) => match &item.kind { + ItemKind::Fn(sig, _, _) => Some(sig), + _ => None, + }, - Node::ImplItem(item) => match &item.kind { - ImplItemKind::Method(sig, _) => Some(sig), - _ => None, - }, + Node::TraitItem(item) => match &item.kind { + TraitItemKind::Method(sig, _) => Some(sig), + _ => None, + }, + Node::ImplItem(item) => match &item.kind { + ImplItemKind::Method(sig, _) => Some(sig), _ => None, - } - } + }, - fn associated_body(self) -> Option { - match self.node { - Node::Item(item) => match item.kind { - ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { - Some(body) - } - _ => None, - }, + _ => None, + } +} - Node::TraitItem(item) => match item.kind { - TraitItemKind::Const(_, Some(body)) - | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), - _ => None, - }, +fn associated_body<'hir>(node: Node<'hir>) -> Option { + match node { + Node::Item(item) => match item.kind { + ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { + Some(body) + } + _ => None, + }, - Node::ImplItem(item) => match item.kind { - ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), - _ => None, - }, + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(_, Some(body)) + | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), + _ => None, + }, - Node::AnonConst(constant) => Some(constant.body), + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), + _ => None, + }, - Node::Expr(expr) => match expr.kind { - ExprKind::Closure(.., body, _, _) => Some(body), - _ => None, - }, + Node::AnonConst(constant) => Some(constant.body), + Node::Expr(expr) => match expr.kind { + ExprKind::Closure(.., body, _, _) => Some(body), _ => None, - } + }, + + _ => None, } +} - fn is_body_owner(self, hir_id: HirId) -> bool { - match self.associated_body() { - Some(b) => b.hir_id == hir_id, - None => false, - } +fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { + match associated_body(node) { + Some(b) => b.hir_id == hir_id, + None => false, } } -/// This type is effectively a `HashMap>`, -/// but it is implemented as 2 layers of arrays. -/// - first we have `A = IndexVec` mapping `DefIndex`s to an inner value -/// - which is `B = IndexVec>` which gives you the `Entry`. -pub(super) type HirEntryMap<'hir> = IndexVec>>>; +/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. +pub struct EarlyMap<'hir> { + pub krate: &'hir Crate<'hir>, + + /// The SVH of the local crate. + pub crate_hash: Svh, + + pub(super) owner_map: FxHashMap>, + pub(super) owner_items_map: FxHashMap>, + + pub(crate) definitions: &'hir Definitions, + + /// The reverse mapping of `node_to_hir_id`. + pub(super) hir_to_node_id: FxHashMap, +} /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. -#[derive(Clone)] pub struct Map<'hir> { - krate: &'hir Crate<'hir>, + pub(super) tcx: TyCtxt<'hir>, - pub dep_graph: DepGraph, + pub(super) krate: &'hir Crate<'hir>, /// The SVH of the local crate. pub crate_hash: Svh, - map: HirEntryMap<'hir>, + pub(super) owner_map: FxHashMap>, + pub(super) owner_items_map: FxHashMap>, - definitions: Definitions, + pub(super) definitions: &'hir Definitions, /// The reverse mapping of `node_to_hir_id`. - hir_to_node_id: FxHashMap, + pub(super) hir_to_node_id: FxHashMap, } struct ParentHirIterator<'map, 'hir> { @@ -197,27 +207,6 @@ impl<'hir> Map<'hir> { &self.krate } - #[inline] - fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { - let local_map = self.map.get(id.owner)?; - local_map.get(id.local_id)?.as_ref() - } - - /// Registers a read in the dependency graph of the AST node with - /// the given `id`. This needs to be called each time a public - /// function returns the HIR for a node -- in other words, when it - /// "reveals" the content of a node to the caller (who might not - /// otherwise have had access to those contents, and hence needs a - /// read recorded). If the function just returns a DefId or - /// HirId, no actual content was returned, so no read is needed. - pub fn read(&self, hir_id: HirId) { - if let Some(entry) = self.lookup(hir_id) { - self.dep_graph.read_index(entry.dep_node); - } else { - bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id) - } - } - #[inline] pub fn definitions(&self) -> &Definitions { &self.definitions @@ -367,7 +356,7 @@ impl<'hir> Map<'hir> { | Node::Lifetime(_) | Node::Visibility(_) | Node::Block(_) - | Node::Crate => return None, + | Node::Crate(_) => return None, Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), Node::GenericParam(param) => match param.kind { GenericParamKind::Lifetime { .. } => return None, @@ -378,54 +367,62 @@ impl<'hir> Map<'hir> { } fn find_entry(&self, id: HirId) -> Option> { - self.lookup(id).cloned() + Some(self.get_entry(id)) } - pub fn item(&self, id: HirId) -> &'hir Item<'hir> { - self.read(id); + fn get_entry(&self, id: HirId) -> Entry<'hir> { + if id.local_id == ItemLocalId::from_u32_const(0) { + let owner = self.tcx.hir_owner(id.owner_def_id()); + Entry { parent: owner.parent, node: owner.node } + } else { + let owner = self.tcx.hir_owner_items(id.owner_def_id()); + let item = owner.items[id.local_id].as_ref().unwrap(); + Entry { parent: HirId { owner: id.owner, local_id: item.parent }, node: item.node } + } + } - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.item(id) + pub fn item(&self, id: HirId) -> &'hir Item<'hir> { + match self.find(id).unwrap() { + Node::Item(item) => item, + _ => bug!(), + } } pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_item(id) + match self.find(id.hir_id).unwrap() { + Node::TraitItem(item) => item, + _ => bug!(), + } } pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.impl_item(id) + match self.find(id.hir_id).unwrap() { + Node::ImplItem(item) => item, + _ => bug!(), + } } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.body(id) + self.tcx + .hir_owner_items(DefId::local(id.hir_id.owner)) + .bodies + .get(&id.hir_id.local_id) + .unwrap() } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_decl() + if let Some(node) = self.find(hir_id) { + fn_decl(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_sig() + if let Some(node) = self.find(hir_id) { + fn_sig(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } @@ -434,7 +431,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.get_parent_node(hir_id); - assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id))); + assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id))); parent } @@ -445,14 +442,8 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(entry) = self.find_entry(hir_id) { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); - } - - entry.associated_body() + if let Some(node) = self.find(hir_id) { + associated_body(node) } else { bug!("no entry for id `{}`", hir_id) } @@ -504,29 +495,24 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] { - self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..]) + self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { - let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); - - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); - &self.krate.attrs + match self.get_entry(CRATE_HIR_ID).node { + Node::Crate(item) => item.attrs, + _ => bug!(), + } } pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = self.as_local_hir_id(module).unwrap(); - self.read(hir_id); - match self.find_entry(hir_id).unwrap().node { + match self.get_entry(hir_id).node { Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), - Node::Crate => (&self.krate.module, self.krate.span, hir_id), + Node::Crate(item) => (&item.module, item.span, hir_id), node => panic!("not a module: {:?}", node), } } @@ -535,15 +521,7 @@ impl<'hir> Map<'hir> { where V: ItemLikeVisitor<'hir>, { - let hir_id = self.as_local_hir_id(module).unwrap(); - - // Read the module so we'll be re-executed if new items - // appear immediately under in the module. If some new item appears - // in some nested item in the module, we'll be re-executed due to reads - // in the expect_* calls the loops below - self.read(hir_id); - - let module = &self.krate.modules[&hir_id]; + let module = self.tcx.hir_module_items(module); for id in &module.items { visitor.visit_item(self.expect_item(*id)); @@ -560,12 +538,11 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { - // read recorded by `find` self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { - self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get` + self.as_local_hir_id(id).map(|id| self.get(id)) } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { @@ -589,13 +566,8 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self - .find_entry(hir_id) - .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) }); - if result.is_some() { - self.read(hir_id); - } - result + let node = self.get_entry(hir_id).node; + if let Node::Crate(..) = node { None } else { Some(node) } } /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there @@ -609,13 +581,7 @@ impl<'hir> Map<'hir> { /// from a node to the root of the HIR (unless you get back the same ID here, /// which can happen if the ID is not in the map itself or is just weird). pub fn get_parent_node(&self, hir_id: HirId) -> HirId { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); - } - - self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) + self.get_entry(hir_id).parent_node().unwrap_or(hir_id) } /// Checks if the node is an argument. An argument is a local variable whose @@ -654,9 +620,9 @@ impl<'hir> Map<'hir> { /// Wether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { - match self.lookup(hir_id) { - Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) - | Some(Entry { node: Node::Crate, .. }) => true, + match self.get_entry(hir_id) { + Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. } + | Entry { node: Node::Crate(..), .. } => true, _ => false, } } @@ -733,7 +699,7 @@ impl<'hir> Map<'hir> { pub fn get_parent_item(&self, hir_id: HirId) -> HirId { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { match node { - Node::Crate + Node::Crate(_) | Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) @@ -852,7 +818,6 @@ impl<'hir> Map<'hir> { node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. } = entry { - self.read(hir_id); // reveals some of the content of a node return nm.abi; } } @@ -861,7 +826,6 @@ impl<'hir> Map<'hir> { pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { match self.find(id) { - // read recorded by `find` Some(Node::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(id)), } @@ -911,7 +875,6 @@ impl<'hir> Map<'hir> { pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> { match self.find(id) { - // read recorded by find Some(Node::Expr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } @@ -943,7 +906,6 @@ impl<'hir> Map<'hir> { /// Given a node ID, gets a list of attributes associated with the AST /// corresponding to the node-ID. pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { - self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { Some(Node::Param(a)) => Some(&a.attrs[..]), Some(Node::Local(l)) => Some(&l.attrs[..]), @@ -960,53 +922,13 @@ impl<'hir> Map<'hir> { // Unit/tuple structs/variants take the attributes straight from // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)), - Some(Node::Crate) => Some(&self.krate.attrs[..]), + Some(Node::Crate(item)) => Some(&item.attrs[..]), _ => None, }; attrs.unwrap_or(&[]) } - /// Returns an iterator that yields all the hir ids in the map. - fn all_ids<'a>(&'a self) -> impl Iterator + 'a { - // This code is a bit awkward because the map is implemented as 2 levels of arrays, - // see the comment on `HirEntryMap`. - // Iterate over all the indices and return a reference to - // local maps and their index given that they exist. - self.map.iter_enumerated().flat_map(move |(owner, local_map)| { - // Iterate over each valid entry in the local map. - local_map.iter_enumerated().filter_map(move |(i, entry)| { - entry.map(move |_| { - // Reconstruct the `HirId` based on the 3 indices we used to find it. - HirId { owner, local_id: i } - }) - }) - }) - } - - /// Returns an iterator that yields the node id's with paths that - /// match `parts`. (Requires `parts` is non-empty.) - /// - /// For example, if given `parts` equal to `["bar", "quux"]`, then - /// the iterator will produce node id's for items with paths - /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and - /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>( - &'a self, - parts: &'a [String], - ) -> impl Iterator + 'a { - let nodes = NodesMatchingSuffix { - map: self, - item_name: parts.last().unwrap(), - in_which: &parts[..parts.len() - 1], - }; - - self.all_ids() - .filter(move |hir| nodes.matches_suffix(*hir)) - .map(move |hir| self.hir_to_node_id(hir)) - } - pub fn span(&self, hir_id: HirId) -> Span { - self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { Some(Node::Param(param)) => param.span, Some(Node::Item(item)) => item.span, @@ -1039,7 +961,7 @@ impl<'hir> Map<'hir> { Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), Some(Node::Local(local)) => local.span, Some(Node::MacroDef(macro_def)) => macro_def.span, - Some(Node::Crate) => self.krate.span, + Some(Node::Crate(item)) => item.span, None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id), } } @@ -1087,82 +1009,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub struct NodesMatchingSuffix<'a> { - map: &'a Map<'a>, - item_name: &'a String, - in_which: &'a [String], -} - -impl<'a> NodesMatchingSuffix<'a> { - /// Returns `true` only if some suffix of the module path for parent - /// matches `self.in_which`. - /// - /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; - /// returns true if parent's path ends with the suffix - /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: HirId) -> bool { - let mut cursor = parent; - for part in self.in_which.iter().rev() { - let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { - None => return false, - Some((node_id, name)) => (node_id, name), - }; - if mod_name.as_str() != *part { - return false; - } - cursor = self.map.get_parent_item(mod_id); - } - return true; - - // Finds the first mod in parent chain for `id`, along with - // that mod's name. - // - // If `id` itself is a mod named `m` with parent `p`, then - // returns `Some(id, m, p)`. If `id` has no mod in its parent - // chain, then returns `None`. - fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> { - loop { - if let Node::Item(item) = map.find(id)? { - if item_is_mod(&item) { - return Some((id, item.ident.name)); - } - } - let parent = map.get_parent_item(id); - if parent == id { - return None; - } - id = parent; - } - - fn item_is_mod(item: &Item<'_>) -> bool { - match item.kind { - ItemKind::Mod(_) => true, - _ => false, - } - } - } - } - - // We are looking at some node `n` with a given name and parent - // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { - name.as_str() == *self.item_name && self.suffix_matches(parent_of_n) - } - - fn matches_suffix(&self, hir: HirId) -> bool { - let name = match self.map.find_entry(hir).map(|entry| entry.node) { - Some(Node::Item(n)) => n.name(), - Some(Node::ForeignItem(n)) => n.name(), - Some(Node::TraitItem(n)) => n.name(), - Some(Node::ImplItem(n)) => n.name(), - Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), - _ => return false, - }; - self.matches_names(self.map.get_parent_item(hir), name) - } -} - trait Named { fn name(&self) -> Name; } @@ -1206,11 +1052,11 @@ impl Named for ImplItem<'_> { pub fn map_crate<'hir>( sess: &rustc_session::Session, + arena: &'hir Arena<'hir>, cstore: &CrateStoreDyn, krate: &'hir Crate<'hir>, - dep_graph: DepGraph, definitions: Definitions, -) -> Map<'hir> { +) -> EarlyMap<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); // Build the reverse mapping of `node_to_hir_id`. @@ -1220,11 +1066,11 @@ pub fn map_crate<'hir>( .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); - let (map, crate_hash) = { + let (owner_map, owner_items_map, crate_hash) = { let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore); let mut collector = - NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx); + NodeCollector::root(sess, arena, krate, &definitions, &hir_to_node_id, hcx); intravisit::walk_crate(&mut collector, krate); let crate_disambiguator = sess.local_crate_disambiguator(); @@ -1232,7 +1078,14 @@ pub fn map_crate<'hir>( collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) }; - let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions }; + let map = EarlyMap { + krate, + crate_hash, + owner_map, + owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), + hir_to_node_id, + definitions: arena.alloc(definitions), + }; sess.time("validate_HIR_map", || { hir_id_validator::check_crate(&map); @@ -1347,7 +1200,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), - Some(Node::Crate) => String::from("root_crate"), + Some(Node::Crate(..)) => String::from("root_crate"), None => format!("unknown node{}", id_str), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2e7e8fdd72491..5dedb54357be0 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -8,11 +8,37 @@ pub mod map; use crate::ty::query::Providers; use crate::ty::TyCtxt; +use rustc_data_structures::cold_path; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::print; +use rustc_hir::Body; use rustc_hir::Crate; +use rustc_hir::HirId; +use rustc_hir::ItemLocalId; +use rustc_hir::Node; +use rustc_index::vec::IndexVec; use std::ops::Deref; +#[derive(HashStable)] +pub struct HirOwner<'tcx> { + parent: HirId, + node: Node<'tcx>, +} + +#[derive(HashStable, Clone)] +pub struct HirItem<'tcx> { + parent: ItemLocalId, + node: Node<'tcx>, +} + +#[derive(HashStable)] +pub struct HirOwnerItems<'tcx> { + //owner: &'tcx HirOwner<'tcx>, + items: IndexVec>>, + bodies: FxHashMap>, +} + /// A wrapper type which allows you to access HIR. #[derive(Clone)] pub struct Hir<'tcx> { @@ -44,11 +70,52 @@ impl<'hir> print::PpAnn for Hir<'hir> { impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> Hir<'tcx> { - Hir { tcx: self, map: &self.hir_map } + let map = self.late_hir_map.load(); + let map = if unlikely!(map.is_none()) { + cold_path(|| { + let map = self.hir_map(LOCAL_CRATE); + self.late_hir_map.store(Some(map)); + map + }) + } else { + map.unwrap() + }; + Hir { tcx: self, map } } } pub fn provide(providers: &mut Providers<'_>) { - providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); + providers.hir_crate = |tcx, _| tcx.hir_map(LOCAL_CRATE).untracked_krate(); + providers.hir_map = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + let early = tcx.hir_map.steal(); + tcx.arena.alloc(map::Map { + tcx, + krate: early.krate, + + crate_hash: early.crate_hash, + + owner_map: early.owner_map, + owner_items_map: early.owner_items_map, + + definitions: early.definitions, + + hir_to_node_id: early.hir_to_node_id, + }) + }; + providers.hir_module_items = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + let hir = tcx.hir(); + let module = hir.as_local_hir_id(id).unwrap(); + &hir.untracked_krate().modules[&module] + }; + providers.hir_owner = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + *tcx.hir().map.owner_map.get(&id.index).unwrap() + }; + providers.hir_owner_items = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + *tcx.hir().map.owner_items_map.get(&id.index).unwrap() + }; map::provide(providers); } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index aade4c3f74c54..25090adfdd387 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -164,15 +164,6 @@ impl<'a> StableHashingContext<'a> { } IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) } - - pub fn hash_hir_item_like(&mut self, f: F) { - let prev_hash_node_ids = self.node_id_hashing_mode; - self.node_id_hashing_mode = NodeIdHashingMode::Ignore; - - f(self); - - self.node_id_hashing_mode = prev_hash_node_ids; - } } /// Something that can provide a stable hashing context. @@ -206,19 +197,6 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} -impl<'a> ToStableHashKey> for hir::HirId { - type KeyType = (DefPathHash, hir::ItemLocalId); - - #[inline] - fn to_stable_hash_key( - &self, - hcx: &StableHashingContext<'a>, - ) -> (DefPathHash, hir::ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner); - (def_path_hash, self.local_id) - } -} - impl<'a> HashStable> for ast::NodeId { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { match hcx.node_id_hashing_mode { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 0155861549773..9f99f0bb8f737 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -6,7 +6,7 @@ use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; use rustc_attr as attr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use smallvec::SmallVec; use std::mem; @@ -111,6 +111,20 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } } + + fn hash_hir_item_like(&mut self, f: F) { + let prev_hash_node_ids = self.node_id_hashing_mode; + self.node_id_hashing_mode = NodeIdHashingMode::Ignore; + + f(self); + + self.node_id_hashing_mode = prev_hash_node_ids; + } + + #[inline] + fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { + self.local_def_path_hash(def_index) + } } impl<'a> ToStableHashKey> for DefId { @@ -164,59 +178,6 @@ impl<'a> ToStableHashKey> for hir::ItemLocalId { } } -impl<'a> HashStable> for hir::TraitItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::ImplItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::ImplItem { - hir_id: _, - ident, - ref vis, - defaultness, - ref attrs, - ref generics, - ref kind, - span, - } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - defaultness.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::Item<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - impl<'a> HashStable> for hir::Body<'_> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index d1bccb961c48b..a6946065583e4 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -55,6 +55,24 @@ rustc_queries! { desc { "get the crate HIR" } } + query hir_map(_: CrateNum) -> &'tcx map::Map<'tcx> { + eval_always + no_hash + desc { "index HIR" } + } + + query hir_module_items(key: DefId) -> &'tcx hir::ModuleItems { + eval_always + } + + query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { + eval_always + } + + query hir_owner_items(key: DefId) -> &'tcx HirOwnerItems<'tcx> { + eval_always + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { cache_on_disk_if { key.is_local() } @@ -644,6 +662,9 @@ rustc_queries! { } TypeChecking { + query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap> { + desc { "local trait impls" } + } query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls { desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index b2973c642a21e..a57dce9973596 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - hir::Node::Crate => return, + hir::Node::Crate(..) => return, _ => {} } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 92c5600362e01..798ee447f2e44 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -5,6 +5,7 @@ use crate::dep_graph::DepGraph; use crate::dep_graph::{self, DepConstructor, DepNode}; use crate::hir::exports::Export; use crate::hir::map as hir_map; +use crate::hir::map::definitions::Definitions; use crate::hir::map::DefPathHash; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; @@ -48,7 +49,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, AtomicCell, Lock, Lrc, WorkerLocal}; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -971,8 +972,11 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - /// This should usually be accessed with the `tcx.hir()` method. - pub(crate) hir_map: hir_map::Map<'tcx>, + /// These should usually be accessed with the `tcx.hir()` method. + pub(crate) hir_map: Steal>, + pub(crate) late_hir_map: AtomicCell>>, + pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + pub(crate) definitions: &'tcx Definitions, /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate /// as well as all upstream crates. Only populated in incremental mode. @@ -1116,7 +1120,8 @@ impl<'tcx> TyCtxt<'tcx> { extern_providers: ty::query::Providers<'tcx>, arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, - hir: hir_map::Map<'tcx>, + hir: hir_map::EarlyMap<'tcx>, + dep_graph: DepGraph, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, output_filenames: &OutputFilenames, @@ -1128,7 +1133,7 @@ impl<'tcx> TyCtxt<'tcx> { let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); - let dep_graph = hir.dep_graph.clone(); + let definitions = hir.definitions; let cstore = resolutions.cstore; let crates = cstore.crates_untracked(); let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); @@ -1139,7 +1144,7 @@ impl<'tcx> TyCtxt<'tcx> { let def_path_tables = crates .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); + .chain(iter::once((LOCAL_CRATE, definitions.def_path_table()))); // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. @@ -1159,7 +1164,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { - let hir_id = hir.node_to_hir_id(k); + let hir_id = definitions.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, StableVec::new(v)); } @@ -1181,28 +1186,33 @@ impl<'tcx> TyCtxt<'tcx> { .export_map .into_iter() .map(|(k, v)| { - let exports: Vec<_> = - v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect(); + let exports: Vec<_> = v + .into_iter() + .map(|e| e.map_id(|id| definitions.node_to_hir_id(id))) + .collect(); (k, exports) }) .collect(), maybe_unused_trait_imports: resolutions .maybe_unused_trait_imports .into_iter() - .map(|id| hir.local_def_id_from_node_id(id)) + .map(|id| definitions.local_def_id(id)) .collect(), maybe_unused_extern_crates: resolutions .maybe_unused_extern_crates .into_iter() - .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp)) + .map(|(id, sp)| (definitions.local_def_id(id), sp)) .collect(), glob_map: resolutions .glob_map .into_iter() - .map(|(id, names)| (hir.local_def_id_from_node_id(id), names)) + .map(|(id, names)| (definitions.local_def_id(id), names)) .collect(), extern_prelude: resolutions.extern_prelude, - hir_map: hir, + untracked_crate: hir.krate, + hir_map: Steal::new(hir), + late_hir_map: AtomicCell::new(None), + definitions, def_path_hash_to_def_id, queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), rcache: Default::default(), @@ -1282,7 +1292,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { if def_id.is_local() { - self.hir().definitions().def_path_hash(def_id.index) + self.definitions.def_path_hash(def_id.index) } else { self.cstore.def_path_hash(def_id) } @@ -1329,9 +1339,9 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let krate = self.gcx.hir_map.untracked_krate(); + let krate = self.gcx.untracked_crate; - StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore) + StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2538322431ec9..6a99430fe8a19 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3012,8 +3012,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); layout::provide(providers); - *providers = - ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers }; + *providers = ty::query::Providers { + trait_impls_of: trait_def::trait_impls_of_provider, + all_local_trait_impls: trait_def::all_local_trait_impls, + ..*providers + }; } /// A map for the local crate mapping each type to a vector of its diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index e7b95af103cc9..29022cac0a65e 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,5 +1,7 @@ use crate::dep_graph::{self, DepNode}; use crate::hir::exports::Export; +use crate::hir::map; +use crate::hir::{HirOwner, HirOwnerItems}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -54,6 +56,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use std::any::type_name; use std::borrow::Cow; +use std::collections::BTreeMap; use std::ops::Deref; use std::sync::Arc; use syntax::ast; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 6d9fff351e9b8..0e156ca660c99 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1176,10 +1176,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { rustc_dep_node_force!([dep_node, tcx] // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already. - DepKind::AllLocalTraitImpls | DepKind::CrateMetadata | - DepKind::HirBody | - DepKind::Hir | // These are anonymous nodes. DepKind::TraitSelect | diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 0cf1c397648ed..91a99ec43e6a9 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -5,11 +5,13 @@ use crate::ty::fast_reject; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::HirId; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; +use std::collections::BTreeMap; /// A trait's definition with type information. #[derive(HashStable)] @@ -146,6 +148,14 @@ impl<'tcx> TyCtxt<'tcx> { } } +// Query provider for `all_local_trait_impls`. +pub(super) fn all_local_trait_impls<'tcx>( + tcx: TyCtxt<'tcx>, + krate: CrateNum, +) -> &'tcx BTreeMap> { + &tcx.hir_crate(krate).trait_impls +} + // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> &TraitImpls { let mut impls = TraitImpls::default(); diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 5816a64fca52c..f0dde892fd195 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -534,9 +534,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id); hir::Crate { - module, - attrs, - span: c.span, + item: hir::CrateItem { module, attrs, span: c.span }, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), items: self.items, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 841827d15fef4..c9466d6ad5dda 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -337,9 +337,9 @@ pub fn start_async_codegen( let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins); + let no_builtins = attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins); let subsystem = - attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem); + attr::first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != sym::windows && subsystem != sym::console { tcx.sess.fatal(&format!( diff --git a/src/librustc_hir/def_id.rs b/src/librustc_hir/def_id.rs index 7ee778ddd8ec7..93ffcc48e10d2 100644 --- a/src/librustc_hir/def_id.rs +++ b/src/librustc_hir/def_id.rs @@ -1,6 +1,9 @@ +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::AtomicRef; use rustc_index::vec::Idx; +use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; +use std::borrow::Borrow; use std::fmt; use std::{u32, u64}; @@ -100,6 +103,28 @@ impl rustc_serialize::UseSpecializedDecodable for CrateNum { } } +#[derive( + Copy, + Clone, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + RustcEncodable, + RustcDecodable, + HashStable_Generic +)] +pub struct DefPathHash(pub Fingerprint); + +impl Borrow for DefPathHash { + #[inline] + fn borrow(&self) -> &Fingerprint { + &self.0 + } +} + rustc_index::newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 0c93a192667e5..4fc1e2c01c9ba 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -579,7 +579,7 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate @@ -588,6 +588,14 @@ pub struct ModuleItems { pub impl_items: BTreeSet, } +/// A type representing only the top-level module. +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +pub struct CrateItem<'hir> { + pub module: Mod<'hir>, + pub attrs: &'hir [Attribute], + pub span: Span, +} + /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -596,9 +604,10 @@ pub struct ModuleItems { /// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Crate<'hir> { - pub module: Mod<'hir>, + /*pub module: Mod<'hir>, pub attrs: &'hir [Attribute], - pub span: Span, + pub span: Span,*/ + pub item: CrateItem<'hir>, pub exported_macros: &'hir [MacroDef<'hir>], // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: &'hir [Attribute], @@ -2588,7 +2597,7 @@ pub type TraitMap = NodeMap>; // imported. pub type GlobMap = NodeMap>; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum Node<'hir> { Param(&'hir Param<'hir>), Item(&'hir Item<'hir>), @@ -2618,7 +2627,7 @@ pub enum Node<'hir> { GenericParam(&'hir GenericParam<'hir>), Visibility(&'hir Visibility<'hir>), - Crate, + Crate(&'hir CrateItem<'hir>), } impl Node<'_> { diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 539a0eee0e312..e6c4b49dd4f1f 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -438,8 +438,8 @@ pub trait Visitor<'v>: Sized { /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID); - walk_list!(visitor, visit_attribute, krate.attrs); + visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); + walk_list!(visitor, visit_attribute, krate.item.attrs); walk_list!(visitor, visit_macro_def, krate.exported_macros); } diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index b0d2f96c71a03..5a126e249e626 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -102,7 +102,7 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), Node::MacroDef(_) => panic!("cannot print MacroDef"), - Node::Crate => panic!("cannot print Crate"), + Node::Crate(..) => panic!("cannot print Crate"), } } } @@ -151,7 +151,7 @@ pub fn print_crate<'a>( // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(&krate.module, &krate.attrs); + s.print_mod(&krate.item.module, &krate.item.attrs); s.print_remaining_comments(); s.s.eof() } diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index 294074cd3e5a4..284e34ed8f0b1 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -1,8 +1,11 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; -use crate::def_id::DefId; -use crate::hir::{BodyId, Expr, ImplItemId, ItemId, Mod, TraitItemId, Ty, VisibilityKind}; -use crate::hir_id::HirId; +use crate::def_id::{DefId, DefIndex, DefPathHash}; +use crate::hir::{ + BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty, + VisibilityKind, +}; +use crate::hir_id::{HirId, ItemLocalId}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro @@ -16,6 +19,36 @@ pub trait HashStableContext: syntax::HashStableContext + rustc_target::HashStabl fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); 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 local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash; +} + +impl ToStableHashKey for HirId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + let def_path_hash = hcx.local_def_path_hash(self.owner); + (def_path_hash, self.local_id) + } +} + +impl ToStableHashKey for TraitItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } +} + +impl ToStableHashKey for ImplItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } } impl HashStable for HirId { @@ -84,3 +117,56 @@ impl HashStable for VisibilityKind<'_> hcx.hash_hir_visibility_kind(self, hasher) } } + +impl HashStable for TraitItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for ImplItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let ImplItem { + hir_id: _, + ident, + ref vis, + defaultness, + ref attrs, + ref generics, + ref kind, + span, + } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + defaultness.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for Item<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 51cc091b6c0af..a56406a1dab11 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { let (if_this_changed, then_this_would_need) = { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; - visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs); + visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs); tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); (visitor.if_this_changed, visitor.then_this_would_need) }; @@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> { if attr.check_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => def_path_hash.to_dep_node(DepKind::Hir), + None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 70abb38278add..671350749c1f0 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { let ams = AssertModuleSource { tcx, available_cgus }; - for attr in tcx.hir().krate().attrs { + for attr in tcx.hir().krate().item.attrs { ams.check_attr(attr); } }) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c5e74868bda4a..27d70473a5dad 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -54,8 +54,7 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ // Hir and HirBody should be computed for all nodes - label_strs::Hir, - label_strs::HirBody, + "Hir", "HirBody", ]; /// `impl` implementation of struct/trait diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6224c4654d695..149b73da2a662 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -716,7 +716,7 @@ pub fn create_global_ctxt<'tcx>( let defs = mem::take(&mut resolver_outputs.definitions); // Construct the HIR map. - let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs); + let hir_map = map::map_crate(sess, &**arena, &*resolver_outputs.cstore, krate, defs); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -743,6 +743,7 @@ pub fn create_global_ctxt<'tcx>( arena, resolver_outputs, hir_map, + dep_graph, query_result_on_disk_cache, &crate_name, &outputs, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca66717ac5eba..90e1fef388ba6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); + self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "crate"); for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 30a3788377508..43b68ca90b796 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -419,7 +419,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. - cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| { + cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate, krate); diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 4f30d2b222684..e8bba52031c8a 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -28,7 +28,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); - let push = builder.levels.push(&krate.attrs, &store); + let push = builder.levels.push(&krate.item.attrs, &store); builder.levels.register_id(hir::CRATE_HIR_ID); for macro_def in krate.exported_macros { builder.levels.register_id(macro_def.hir_id); diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 8d018b9bb94dd..13668b2423fdd 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -8,7 +8,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { args: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); - for attr in tcx.hir().krate().attrs.iter() { + for attr in tcx.hir().krate().item.attrs.iter() { if attr.has_name(sym::link_args) { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 58cf142ab3a36..b351a667e8bf9 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -3,7 +3,7 @@ use crate::rmeta::table::{FixedSizeEncoding, Table}; use crate::rmeta::*; -use rustc::dep_graph::{self, DepNodeIndex}; +use rustc::dep_graph::{self, DepNode, DepNodeIndex}; use rustc::hir::exports::Export; use rustc::hir::map::definitions::DefPathTable; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; @@ -1536,7 +1536,8 @@ impl<'a, 'tcx> CrateMetadata { // would always write the same value. let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); - let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata); + let dep_node = + DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata); dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); assert!(dep_node_index != DepNodeIndex::INVALID); diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 4133047af78fe..901ef6b7a8d97 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -332,7 +332,7 @@ impl<'tcx> EncodeContext<'tcx> { fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in krate.exported_macros { self.visit_macro_def(macro_def); diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index ebd93e9ab85b8..5f7e19a562df7 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -59,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { } // If the user wants no main function at all, then stop here. - if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) { + if attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_main) { return None; } @@ -157,7 +157,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().span; + let sp = tcx.hir().krate().item.span; if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 4009cc6d725ab..40ec36af374f0 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -404,8 +404,8 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { annotator.annotate( hir::CRATE_HIR_ID, - &krate.attrs, - krate.span, + &krate.item.attrs, + krate.item.span, AnnotationKind::Required, |v| intravisit::walk_crate(v, krate), ); @@ -529,7 +529,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(hir::CRATE_HIR_ID, krate.span, "crate"); + missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate"); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f140f11b09098..76141770e95dc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -141,6 +141,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() @@ -194,6 +195,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0c7dfa1417a97..cbb39f7966cf5 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -112,7 +112,7 @@ pub fn run(options: Options) -> i32 { compiler.session().opts.unstable_features.is_nightly_build(), ), }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + hir_collector.visit_testable("".to_string(), &krate.item.attrs, |this| { intravisit::walk_crate(this, krate); }); }); @@ -146,6 +146,7 @@ fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions { TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() }; let test_attrs: Vec<_> = krate + .item .attrs .iter() .filter(|a| a.check_name(sym::doc)) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index d3d45ccccad36..38eae49177bce 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -64,11 +64,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> { let mut module = self.visit_mod_contents( - krate.span, - krate.attrs, + krate.item.span, + krate.item.attrs, &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, - &krate.module, + &krate.item.module, None, ); // Attach the crate's exported macros to the top-level module: