diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 663c408ac22f..e8c1cd36064e 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -79,6 +79,16 @@ struct DepGraphData { loaded_from_cache: Lock>, } +pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option +where + R: for<'a> HashStable>, +{ + let mut stable_hasher = StableHasher::new(); + result.hash_stable(hcx, &mut stable_hasher); + + Some(stable_hasher.finish()) +} + impl DepGraph { pub fn new(prev_graph: PreviousDepGraph, @@ -178,14 +188,16 @@ impl DepGraph { /// `arg` parameter. /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html - pub fn with_task<'gcx, C, A, R>(&self, - key: DepNode, - cx: C, - arg: A, - task: fn(C, A) -> R) - -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider<'gcx>, - R: HashStable>, + pub fn with_task<'a, C, A, R>( + &self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R, + hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, + ) -> (R, DepNodeIndex) + where + C: DepGraphSafe + StableHashingContextProvider<'a>, { self.with_task_impl(key, cx, arg, false, task, |_key| Some(TaskDeps { @@ -196,17 +208,18 @@ impl DepGraph { }), |data, key, fingerprint, task| { data.borrow_mut().complete_task(key, task.unwrap(), fingerprint) - }) + }, + hash_result) } /// Creates a new dep-graph input with value `input` - pub fn input_task<'gcx, C, R>(&self, + pub fn input_task<'a, C, R>(&self, key: DepNode, cx: C, input: R) -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider<'gcx>, - R: HashStable>, + where C: DepGraphSafe + StableHashingContextProvider<'a>, + R: for<'b> HashStable>, { fn identity_fn(_: C, arg: A) -> A { arg @@ -216,10 +229,11 @@ impl DepGraph { |_| None, |data, key, fingerprint, _| { data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) - }) + }, + hash_result::) } - fn with_task_impl<'gcx, C, A, R>( + fn with_task_impl<'a, C, A, R>( &self, key: DepNode, cx: C, @@ -230,11 +244,11 @@ impl DepGraph { finish_task_and_alloc_depnode: fn(&Lock, DepNode, Fingerprint, - Option) -> DepNodeIndex + Option) -> DepNodeIndex, + hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, ) -> (R, DepNodeIndex) where - C: DepGraphSafe + StableHashingContextProvider<'gcx>, - R: HashStable>, + C: DepGraphSafe + StableHashingContextProvider<'a>, { if let Some(ref data) = self.data { let task_deps = create_task(key).map(|deps| Lock::new(deps)); @@ -269,15 +283,12 @@ impl DepGraph { profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) }; - let mut stable_hasher = StableHasher::new(); - result.hash_stable(&mut hcx, &mut stable_hasher); - - let current_fingerprint = stable_hasher.finish(); + let current_fingerprint = hash_result(&mut hcx, &result); let dep_node_index = finish_task_and_alloc_depnode( &data.current, key, - current_fingerprint, + current_fingerprint.unwrap_or(Fingerprint::ZERO), task_deps.map(|lock| lock.into_inner()), ); @@ -285,15 +296,20 @@ impl DepGraph { if let Some(prev_index) = data.previous.node_to_index_opt(&key) { let prev_fingerprint = data.previous.fingerprint_by_index(prev_index); - let color = if current_fingerprint == prev_fingerprint { - DepNodeColor::Green(dep_node_index) + let color = if let Some(current_fingerprint) = current_fingerprint { + if current_fingerprint == prev_fingerprint { + DepNodeColor::Green(dep_node_index) + } else { + DepNodeColor::Red + } } else { + // Mark the node as Red if we can't hash the result DepNodeColor::Red }; debug_assert!(data.colors.get(prev_index).is_none(), - "DepGraph::with_task() - Duplicate DepNodeColor \ - insertion for {:?}", key); + "DepGraph::with_task() - Duplicate DepNodeColor \ + insertion for {:?}", key); data.colors.insert(prev_index, color); } @@ -342,14 +358,16 @@ impl DepGraph { /// Execute something within an "eval-always" task which is a task // that runs whenever anything changes. - pub fn with_eval_always_task<'gcx, C, A, R>(&self, - key: DepNode, - cx: C, - arg: A, - task: fn(C, A) -> R) - -> (R, DepNodeIndex) - where C: DepGraphSafe + StableHashingContextProvider<'gcx>, - R: HashStable>, + pub fn with_eval_always_task<'a, C, A, R>( + &self, + key: DepNode, + cx: C, + arg: A, + task: fn(C, A) -> R, + hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option, + ) -> (R, DepNodeIndex) + where + C: DepGraphSafe + StableHashingContextProvider<'a>, { self.with_task_impl(key, cx, arg, false, task, |_| None, @@ -359,7 +377,8 @@ impl DepGraph { &DepNode::new_no_params(DepKind::Krate) ]; current.alloc_node(key, smallvec![krate_idx], fingerprint) - }) + }, + hash_result) } #[inline] diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index 022caabcbf3a..b84d2ad14588 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -10,7 +10,7 @@ pub mod cgu_reuse_tracker; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs}; -pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps}; +pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result}; pub use self::graph::WorkProductFileKind; pub use self::prev::PreviousDepGraph; pub use self::query::DepGraphQuery; diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index f84bb77e29b2..37552f18f4a0 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -48,14 +48,14 @@ pub(super) struct NodeCollector<'a, 'hir> { hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } -fn input_dep_node_and_hash<'a, I>( +fn input_dep_node_and_hash( dep_graph: &DepGraph, - hcx: &mut StableHashingContext<'a>, + hcx: &mut StableHashingContext<'_>, dep_node: DepNode, input: I, ) -> (DepNodeIndex, Fingerprint) where - I: HashStable>, + I: for<'a> HashStable>, { let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; @@ -70,15 +70,15 @@ where (dep_node_index, hash) } -fn alloc_hir_dep_nodes<'a, I>( +fn alloc_hir_dep_nodes( dep_graph: &DepGraph, - hcx: &mut StableHashingContext<'a>, + hcx: &mut StableHashingContext<'_>, def_path_hash: DefPathHash, item_like: I, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, ) -> (DepNodeIndex, DepNodeIndex) where - I: HashStable>, + I: for<'a> HashStable>, { let sig = dep_graph.input_task( def_path_hash.to_dep_node(DepKind::Hir), @@ -286,7 +286,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.parent_node = parent_node; } - fn with_dep_node_owner>, + fn with_dep_node_owner HashStable>, F: FnOnce(&mut Self)>(&mut self, dep_node_owner: DefIndex, item_like: &T, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 140c772256d3..795853a37c75 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1,7 +1,7 @@ //! type context book-keeping use crate::dep_graph::DepGraph; -use crate::dep_graph::{DepNode, DepConstructor}; +use crate::dep_graph::{self, DepNode, DepConstructor}; use crate::errors::DiagnosticBuilder; use crate::session::Session; use crate::session::config::{BorrowckMode, OutputFilenames}; @@ -1435,7 +1435,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.dep_graph.with_task(dep_node, self, crate_hash, - |_, x| x // No transformation needed + |_, x| x, // No transformation needed + dep_graph::hash_result, ); } } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 255e39eaccd6..a3ee92f8e126 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -20,7 +20,7 @@ use std::hash::Hash; use std::fmt::Debug; use syntax_pos::symbol::InternedString; use rustc_data_structures::sync::Lock; -use rustc_data_structures::stable_hasher::HashStable; +use rustc_data_structures::fingerprint::Fingerprint; use crate::ich::StableHashingContext; // Query configuration and description traits. @@ -30,7 +30,7 @@ pub trait QueryConfig<'tcx> { const CATEGORY: ProfileCategory; type Key: Eq + Hash + Clone + Debug; - type Value: Clone + for<'a> HashStable>; + type Value: Clone; } pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { @@ -44,6 +44,11 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value; + fn hash_result( + hcx: &mut StableHashingContext<'_>, + result: &Self::Value + ) -> Option; + fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value; } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 20a700bb58dd..8211dc50fc6e 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{DepConstructor, DepNode}; +use crate::dep_graph::{self, DepConstructor, DepNode}; use crate::errors::DiagnosticBuilder; use crate::hir::def_id::{CrateNum, DefId, DefIndex}; use crate::hir::def::{Def, Export}; @@ -49,6 +49,7 @@ use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::StableVec; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_target::spec::PanicStrategy; use std::borrow::Cow; @@ -227,19 +228,19 @@ define_queries! { <'tcx> /// Fetch the MIR for a given def-id right after it's built - this includes /// unreachable code. - [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal>, + [no_hash] fn mir_built: MirBuilt(DefId) -> &'tcx Steal>, /// Fetch the MIR for a given def-id up till the point where it is /// ready for const evaluation. /// /// See the README for the `mir` module for details. - [] fn mir_const: MirConst(DefId) -> &'tcx Steal>, + [no_hash] fn mir_const: MirConst(DefId) -> &'tcx Steal>, - [] fn mir_validated: MirValidated(DefId) -> &'tcx Steal>, + [no_hash] fn mir_validated: MirValidated(DefId) -> &'tcx Steal>, /// MIR after our optimization passes have run. This is MIR that is ready /// for codegen. This is also the only query that can fetch non-local MIR, at present. - [] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>, + [no_hash] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>, }, TypeChecking { @@ -282,7 +283,7 @@ define_queries! { <'tcx> TypeChecking { [] fn typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult, - [] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, + [no_hash] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, }, Other { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index a26b21a1059f..3dcb939d6360 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -499,7 +499,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { dep_node: &DepNode, dep_node_index: DepNodeIndex, ) { - use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use crate::ich::Fingerprint; assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == @@ -509,11 +508,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { debug!("BEGIN verify_ich({:?})", dep_node); let mut hcx = self.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - result.hash_stable(&mut hcx, &mut hasher); - - let new_hash: Fingerprint = hasher.finish(); + let new_hash = Q::hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO); debug!("END verify_ich({:?})", dep_node); let old_hash = self.dep_graph.fingerprint_of(dep_node_index); @@ -549,12 +545,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { tcx.dep_graph.with_eval_always_task(dep_node, tcx, key, - Q::compute) + Q::compute, + Q::hash_result) } else { tcx.dep_graph.with_task(dep_node, tcx, key, - Q::compute) + Q::compute, + Q::hash_result) } }) }); @@ -679,6 +677,18 @@ macro_rules! handle_cycle_error { }; } +macro_rules! hash_result { + ([][$hcx:expr, $result:expr]) => {{ + dep_graph::hash_result($hcx, &$result) + }}; + ([no_hash$(, $modifiers:ident)*][$hcx:expr, $result:expr]) => {{ + None + }}; + ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => { + hash_result!([$($modifiers),*][$($args)*]) + }; +} + macro_rules! define_queries { (<$tcx:tt> $($category:tt { $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* @@ -966,6 +976,13 @@ macro_rules! define_queries_inner { }) } + fn hash_result( + _hcx: &mut StableHashingContext<'_>, + _result: &Self::Value + ) -> Option { + hash_result!([$($modifiers)*][_hcx, _result]) + } + fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value { handle_cycle_error!([$($modifiers)*][tcx]) } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 6e1ef440a3f3..d9f44ca6e45a 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -20,6 +20,7 @@ use super::LlvmCodegenBackend; use llvm; use metadata; +use rustc::dep_graph; use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::TyCtxt; @@ -145,7 +146,8 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, tcx, cgu_name, - module_codegen); + module_codegen, + dep_graph::hash_result); let time_to_codegen = start_time.elapsed(); // We assume that the cost to run LLVM on a CGU is proportional to