diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 80b95b99b16..f95ad9f3a9b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -41,7 +41,9 @@ use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; @@ -467,7 +469,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - hir::OwnerInfo { node, attrs, bodies, trait_map } + let (hash, node_hash) = self.hash_body(node, &bodies); + + hir::OwnerInfo { hash, node_hash, node, attrs, bodies, trait_map } + } + + /// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate + /// queries which depend on the full HIR tree and those which only depend on the item signature. + fn hash_body( + &mut self, + node: hir::OwnerNode<'hir>, + bodies: &IndexVec>>, + ) -> (Fingerprint, Fingerprint) { + let mut hcx = self.resolver.create_stable_hashing_context(); + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(true, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let full_hash = stable_hasher.finish(); + let mut stable_hasher = StableHasher::new(); + hcx.with_hir_bodies(false, node.def_id(), bodies, |hcx| { + node.hash_stable(hcx, &mut stable_hasher) + }); + let node_hash = stable_hasher.finish(); + (full_hash, node_hash) } /// This method allocates a new `HirId` for the given `NodeId` and stores it in diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1d1c0a0de13..44652d0198f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -9,6 +9,7 @@ use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObject pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto}; pub use rustc_ast::{CaptureBy, Movability, Mutability}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; @@ -670,6 +671,10 @@ pub struct OwnerInfo<'hir> { /// 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, } /// The top-level data structure that stores the entire contents of diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 80e48a4f74b..2499ef8bc60 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -1,9 +1,7 @@ use crate::arena::Arena; use crate::hir::map::Map; use crate::hir::{IndexedHir, OwnerNodes, ParentedNode}; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; @@ -11,7 +9,6 @@ use rustc_hir::definitions; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; -use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::{Span, DUMMY_SP}; @@ -37,8 +34,6 @@ pub(super) struct NodeCollector<'a, 'hir> { current_dep_node_owner: LocalDefId, definitions: &'a definitions::Definitions, - - hcx: StableHashingContext<'a>, } fn insert_vec_map(map: &mut IndexVec>, k: K, v: V) { @@ -51,27 +46,12 @@ fn insert_vec_map(map: &mut IndexVec>, k: K, v: V map[k] = Some(v); } -fn hash_body<'s, 'hir: 's>( - hcx: &mut StableHashingContext<'s>, - item_like: impl for<'a> HashStable>, - hash_bodies: bool, - owner: LocalDefId, - bodies: &'hir IndexVec>>, -) -> Fingerprint { - let mut stable_hasher = StableHasher::new(); - hcx.with_hir_bodies(hash_bodies, owner, bodies, |hcx| { - item_like.hash_stable(hcx, &mut stable_hasher) - }); - stable_hasher.finish() -} - 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, - hcx: StableHashingContext<'a>, ) -> NodeCollector<'a, 'hir> { let mut collector = NodeCollector { arena, @@ -80,7 +60,6 @@ impl<'a, 'hir: 'a> NodeCollector<'a, 'hir> { parent_node: hir::CRATE_HIR_ID, current_dep_node_owner: CRATE_DEF_ID, definitions, - hcx, map: IndexVec::from_fn_n(|_| None, definitions.def_index_count()), parenting: FxHashMap::default(), }; @@ -97,10 +76,10 @@ impl<'a, 'hir: 'a> NodeCollector<'a, 'hir> { let mut nodes = IndexVec::new(); nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: node.into() })); - let bodies = &self.krate.owners[owner].as_ref().unwrap().bodies; - - let hash = hash_body(&mut self.hcx, node, true, owner, bodies); - let node_hash = hash_body(&mut self.hcx, node, false, owner, bodies); + 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 })); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 8c11fd8a280..89f4ec4d9f6 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1071,13 +1071,11 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); // We can access untracked state since we are an eval_always query. - let hcx = tcx.create_stable_hashing_context(); let mut collector = NodeCollector::root( tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.untracked_resolutions.definitions, - hcx, ); let top_mod = tcx.untracked_crate.module(); collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);