diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 81f30411b25ad..5c3b7ad294620 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -178,6 +178,10 @@ impl fmt::Debug for DepNode { /// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual /// jump table instead of large matches. pub struct DepKindVTable<'tcx> { + /// If true, dep nodes of this kind that would have no dependencies can be + /// replaced with `SINGLETON_ZERO_DEPS_ANON_NODE`. + pub anonymizable: bool, + /// Eval-always queries do not track their dependencies, and are always recomputed, even if /// their inputs have not changed since the last compiler invocation. The result is still /// cached within one compiler invocation. diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index d0d7d581b4395..2939f15b7d140 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -327,14 +327,14 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub fn with_task<'tcx, A: Debug, R>( + pub fn with_task<'tcx, A: Debug, V>( &self, dep_node: DepNode, tcx: TyCtxt<'tcx>, task_arg: A, - task_fn: fn(tcx: TyCtxt<'tcx>, task_arg: A) -> R, - hash_result: Option, &R) -> Fingerprint>, - ) -> (R, DepNodeIndex) { + task_fn: fn(tcx: TyCtxt<'tcx>, task_arg: A) -> V, + hash_value_fn: Option, &V) -> Fingerprint>, + ) -> (V, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: // 1. Something is wrong with DepNode creation, either here or // in `DepGraph::try_mark_green()`. @@ -348,22 +348,32 @@ impl DepGraphData { ) }); - let with_deps = |task_deps| with_deps(task_deps, || task_fn(tcx, task_arg)); - let (result, edges) = if tcx.is_eval_always(dep_node.kind) { - (with_deps(TaskDepsRef::EvalAlways), EdgesVec::new()) + let exec_task_with_dep_tracking = + |task_deps| with_deps(task_deps, || task_fn(tcx, task_arg)); + let value; + let edges; + + if tcx.is_eval_always(dep_node.kind) { + value = exec_task_with_dep_tracking(TaskDepsRef::EvalAlways); + edges = EdgesVec::new(); } else { let task_deps = Lock::new(TaskDeps::new( #[cfg(debug_assertions)] Some(dep_node), 0, )); - (with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads) + value = exec_task_with_dep_tracking(TaskDepsRef::Allow(&task_deps)); + edges = task_deps.into_inner().reads; + + if edges.is_empty() && tcx.dep_kind_vtable(dep_node.kind).anonymizable { + return (value, DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE); + } }; let dep_node_index = - self.hash_result_and_alloc_node(tcx, dep_node, edges, &result, hash_result); + self.hash_result_and_alloc_node(tcx, dep_node, edges, &value, hash_value_fn); - (result, dep_node_index) + (value, dep_node_index) } /// Executes something within an "anonymous" task, that is, a task the diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index 44b92dc727abe..24c3bc397284a 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -14,6 +14,7 @@ mod non_query { // We use this for most things when incr. comp. is turned off. pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Unit, force_from_dep_node_fn: Some(|_, dep_node, _| { @@ -26,6 +27,7 @@ mod non_query { // We use this for the forever-red node. pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Unit, force_from_dep_node_fn: Some(|_, dep_node, _| { @@ -37,6 +39,7 @@ mod non_query { pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Unit, force_from_dep_node_fn: Some(|tcx, _, prev_index| { @@ -49,6 +52,7 @@ mod non_query { pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Opaque, force_from_dep_node_fn: Some(|_, _, _| bug!("cannot force an anon node")), @@ -58,6 +62,7 @@ mod non_query { pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Unit, force_from_dep_node_fn: None, @@ -67,6 +72,7 @@ mod non_query { pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Opaque, force_from_dep_node_fn: None, @@ -76,6 +82,7 @@ mod non_query { pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Opaque, force_from_dep_node_fn: None, @@ -85,6 +92,7 @@ mod non_query { pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { + anonymizable: false, is_eval_always: false, key_fingerprint_style: KeyFingerprintStyle::Unit, force_from_dep_node_fn: None, @@ -108,7 +116,10 @@ where let key_fingerprint_style = ::Key::key_fingerprint_style(); let can_recover = key_fingerprint_style.is_maybe_recoverable(); + let anonymizable = !is_cache_on_disk && !can_recover && !is_eval_always; + DepKindVTable { + anonymizable, is_eval_always, key_fingerprint_style, force_from_dep_node_fn: (can_recover && !is_no_force)