about summary refs log tree commit diff
path: root/compiler/rustc_query_system/src/dep_graph/graph.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_query_system/src/dep_graph/graph.rs')
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs105
1 files changed, 63 insertions, 42 deletions
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 3109d53cd2c..de681328bcb 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -5,13 +5,14 @@ use std::marker::PhantomData;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicU32, Ordering};
 
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
 use rustc_data_structures::sharded::{self, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_data_structures::unord::UnordMap;
+use rustc_errors::DiagInner;
 use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
@@ -91,8 +92,6 @@ pub(crate) struct DepGraphData<D: Deps> {
 
     colors: DepNodeColorMap,
 
-    processed_side_effects: Lock<FxHashSet<DepNodeIndex>>,
-
     /// When we load, there may be `.o` files, cached MIR, or other such
     /// things available to us. If we find that they are not dirty, we
     /// load the path to the file storing those work-products here into
@@ -174,7 +173,6 @@ impl<D: Deps> DepGraph<D> {
                 previous_work_products: prev_work_products,
                 dep_node_debug: Default::default(),
                 current,
-                processed_side_effects: Default::default(),
                 previous: prev_graph,
                 colors,
                 debug_loaded_from_disk: Default::default(),
@@ -535,6 +533,24 @@ impl<D: Deps> DepGraph<D> {
         }
     }
 
+    #[inline]
+    pub fn record_diagnostic<Qcx: QueryContext>(&self, qcx: Qcx, diagnostic: &DiagInner) {
+        if let Some(ref data) = self.data {
+            self.read_index(data.encode_diagnostic(qcx, diagnostic));
+        }
+    }
+
+    #[inline]
+    pub fn force_diagnostic_node<Qcx: QueryContext>(
+        &self,
+        qcx: Qcx,
+        prev_index: SerializedDepNodeIndex,
+    ) {
+        if let Some(ref data) = self.data {
+            data.force_diagnostic_node(qcx, prev_index);
+        }
+    }
+
     /// Create a node when we force-feed a value into the query cache.
     /// This is used to remove cycles during type-checking const generic parameters.
     ///
@@ -656,6 +672,48 @@ impl<D: Deps> DepGraphData<D> {
     pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) {
         self.debug_loaded_from_disk.lock().insert(dep_node);
     }
+
+    #[inline]
+    fn encode_diagnostic<Qcx: QueryContext>(
+        &self,
+        qcx: Qcx,
+        diagnostic: &DiagInner,
+    ) -> DepNodeIndex {
+        let dep_node_index = self.current.encoder.send(
+            DepNode {
+                kind: D::DEP_KIND_SIDE_EFFECT,
+                hash: PackedFingerprint::from(Fingerprint::ZERO),
+            },
+            Fingerprint::ZERO,
+            // We want the side effect node to always be red so it will be forced and emit the
+            // diagnostic.
+            std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
+        );
+        let side_effects = QuerySideEffects { diagnostic: diagnostic.clone() };
+        qcx.store_side_effects(dep_node_index, side_effects);
+        dep_node_index
+    }
+
+    #[inline]
+    fn force_diagnostic_node<Qcx: QueryContext>(
+        &self,
+        qcx: Qcx,
+        prev_index: SerializedDepNodeIndex,
+    ) {
+        D::with_deps(TaskDepsRef::Ignore, || {
+            let side_effects = qcx.load_side_effects(prev_index).unwrap();
+
+            qcx.dep_context().sess().dcx().emit_diagnostic(side_effects.diagnostic.clone());
+
+            // Promote the previous diagnostics to the current session.
+            let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index);
+            // FIXME: Can this race with a parallel compiler?
+            qcx.store_side_effects(index, side_effects);
+
+            // Mark the node as green.
+            self.colors.insert(prev_index, DepNodeColor::Green(index));
+        })
+    }
 }
 
 impl<D: Deps> DepGraph<D> {
@@ -794,7 +852,7 @@ impl<D: Deps> DepGraphData<D> {
 
         // We failed to mark it green, so we try to force the query.
         debug!("trying to force dependency {dep_dep_node:?}");
-        if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) {
+        if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) {
             // The DepNode could not be forced.
             debug!("dependency {dep_dep_node:?} could not be forced");
             return None;
@@ -867,16 +925,6 @@ impl<D: Deps> DepGraphData<D> {
 
         // ... emitting any stored diagnostic ...
 
-        // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
-        // Maybe store a list on disk and encode this fact in the DepNodeState
-        let side_effects = qcx.load_side_effects(prev_dep_node_index);
-
-        if side_effects.maybe_any() {
-            qcx.dep_context().dep_graph().with_query_deserialization(|| {
-                self.emit_side_effects(qcx, dep_node_index, side_effects)
-            });
-        }
-
         // ... and finally storing a "Green" entry in the color map.
         // Multiple threads can all write the same color here
         self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
@@ -884,33 +932,6 @@ impl<D: Deps> DepGraphData<D> {
         debug!("successfully marked {dep_node:?} as green");
         Some(dep_node_index)
     }
-
-    /// Atomically emits some loaded diagnostics.
-    /// This may be called concurrently on multiple threads for the same dep node.
-    #[cold]
-    #[inline(never)]
-    fn emit_side_effects<Qcx: QueryContext<Deps = D>>(
-        &self,
-        qcx: Qcx,
-        dep_node_index: DepNodeIndex,
-        side_effects: QuerySideEffects,
-    ) {
-        let mut processed = self.processed_side_effects.lock();
-
-        if processed.insert(dep_node_index) {
-            // We were the first to insert the node in the set so this thread
-            // must process side effects
-
-            // Promote the previous diagnostics to the current session.
-            qcx.store_side_effects(dep_node_index, side_effects.clone());
-
-            let dcx = qcx.dep_context().sess().dcx();
-
-            for diagnostic in side_effects.diagnostics {
-                dcx.emit_diagnostic(diagnostic);
-            }
-        }
-    }
 }
 
 impl<D: Deps> DepGraph<D> {