-
Notifications
You must be signed in to change notification settings - Fork 14.1k
add with_hash_task to generate DepNode deterministically
#100987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
with_hash_task to generate DepNode deterministically
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,13 +49,17 @@ use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRe | |
| use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable}; | ||
| use rustc_span::symbol::sym; | ||
|
|
||
| use rustc_data_structures::fingerprint::Fingerprint; | ||
| use rustc_data_structures::stable_hasher::StableHasher; | ||
| use std::cell::{Cell, RefCell}; | ||
| use std::cmp; | ||
| use std::fmt::{self, Display}; | ||
| use std::hash::Hash; | ||
| use std::iter; | ||
|
|
||
| pub use rustc_middle::traits::select::*; | ||
| use rustc_middle::ty::print::with_no_trimmed_paths; | ||
| use rustc_query_system::dep_graph::TaskDeps; | ||
|
|
||
| mod candidate_assembly; | ||
| mod confirmation; | ||
|
|
@@ -1017,7 +1021,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
| return Ok(cycle_result); | ||
| } | ||
|
|
||
| let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack)); | ||
| let (result, dep_node) = if cfg!(parallel_compiler) { | ||
|
||
| self.in_task_with_hash( | ||
| |this| this.evaluate_stack(&stack), | ||
| |_| { | ||
| let mut hasher = StableHasher::new(); | ||
| (param_env, fresh_trait_pred).hash(&mut hasher); | ||
| hasher.finish() | ||
| }, | ||
| ) | ||
| } else { | ||
| self.in_task(|this| this.evaluate_stack(&stack)) | ||
| }; | ||
|
|
||
| let result = result?; | ||
|
|
||
| if !result.must_apply_modulo_regions() { | ||
|
|
@@ -1263,17 +1279,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
| if self.can_use_global_caches(param_env) { | ||
| if !trait_pred.needs_infer() { | ||
| debug!(?trait_pred, ?result, "insert_evaluation_cache global"); | ||
| // This may overwrite the cache with the same value | ||
| // FIXME: Due to #50507 this overwrites the different values | ||
| // This should be changed to use HashMapExt::insert_same | ||
| // when that is fixed | ||
| self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result); | ||
| self.tcx().evaluation_cache.insert_same((param_env, trait_pred), dep_node, result); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| debug!(?trait_pred, ?result, "insert_evaluation_cache"); | ||
| self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result); | ||
| self.infcx.evaluation_cache.insert_same((param_env, trait_pred), dep_node, result); | ||
| } | ||
|
|
||
| /// For various reasons, it's possible for a subobligation | ||
|
|
@@ -1344,6 +1356,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
| (result, dep_node) | ||
| } | ||
|
|
||
| fn in_task_with_hash<OP, R, H>(&mut self, op: OP, hash: H) -> (R, DepNodeIndex) | ||
| where | ||
| OP: FnOnce(&mut Self) -> R, | ||
| H: FnOnce(&TaskDeps<DepKind>) -> Fingerprint, | ||
| { | ||
| let (result, dep_node) = self.tcx().dep_graph.with_hash_task( | ||
| self.tcx(), | ||
| DepKind::TraitSelect, | ||
| || op(self), | ||
| hash, | ||
| ); | ||
| self.tcx().dep_graph.read_index(dep_node); | ||
| (result, dep_node) | ||
| } | ||
|
|
||
| /// filter_impls filters constant trait obligations and candidates that have a positive impl | ||
| /// for a negative goal and a negative impl for a positive goal | ||
| #[instrument(level = "debug", skip(self, candidates))] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea for a simpler solution: could we hash the
DepNodeinstead of theDepNodeIndexto avoid order-dependence? Could this solve the issue without having to make client code do the hashing?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good advice, but
DepNodeinTaskDepsonly exists in the case of#[cfg(debug_assert)]. I'm usingHashbound now in where clause ofwith_task_hash, which can avoid hashing in client code.