| pub mod debug; |
| pub mod dep_node; |
| mod edges; |
| mod graph; |
| mod query; |
| mod serialized; |
| |
| use std::panic; |
| |
| pub use dep_node::{DepKind, DepKindStruct, DepNode, DepNodeParams, WorkProductId}; |
| pub(crate) use graph::DepGraphData; |
| pub use graph::{DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result}; |
| pub use query::DepGraphQuery; |
| use rustc_data_structures::profiling::SelfProfilerRef; |
| use rustc_data_structures::sync::DynSync; |
| use rustc_session::Session; |
| pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; |
| use tracing::instrument; |
| |
| use self::graph::{MarkFrame, print_markframe_trace}; |
| use crate::ich::StableHashingContext; |
| |
| pub trait DepContext: Copy { |
| type Deps: Deps; |
| |
| /// Create a hashing context for hashing new results. |
| fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R; |
| |
| /// Access the DepGraph. |
| fn dep_graph(&self) -> &DepGraph<Self::Deps>; |
| |
| /// Access the profiler. |
| fn profiler(&self) -> &SelfProfilerRef; |
| |
| /// Access the compiler session. |
| fn sess(&self) -> &Session; |
| |
| fn dep_kind_info(&self, dep_node: DepKind) -> &DepKindStruct<Self>; |
| |
| #[inline(always)] |
| fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { |
| let data = self.dep_kind_info(kind); |
| if data.is_anon { |
| return FingerprintStyle::Opaque; |
| } |
| data.fingerprint_style |
| } |
| |
| #[inline(always)] |
| /// Return whether this kind always require evaluation. |
| fn is_eval_always(self, kind: DepKind) -> bool { |
| self.dep_kind_info(kind).is_eval_always |
| } |
| |
| /// Try to force a dep node to execute and see if it's green. |
| /// |
| /// Returns true if the query has actually been forced. It is valid that a query |
| /// fails to be forced, e.g. when the query key cannot be reconstructed from the |
| /// dep-node or when the query kind outright does not support it. |
| #[inline] |
| #[instrument(skip(self, frame), level = "debug")] |
| fn try_force_from_dep_node( |
| self, |
| dep_node: DepNode, |
| prev_index: SerializedDepNodeIndex, |
| frame: Option<&MarkFrame<'_>>, |
| ) -> bool { |
| let cb = self.dep_kind_info(dep_node.kind); |
| if let Some(f) = cb.force_from_dep_node { |
| match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node, prev_index))) { |
| Err(value) => { |
| if !value.is::<rustc_errors::FatalErrorMarker>() { |
| print_markframe_trace(self.dep_graph(), frame); |
| } |
| panic::resume_unwind(value) |
| } |
| Ok(query_has_been_forced) => query_has_been_forced, |
| } |
| } else { |
| false |
| } |
| } |
| |
| /// Load data from the on-disk cache. |
| fn try_load_from_on_disk_cache(self, dep_node: DepNode) { |
| let cb = self.dep_kind_info(dep_node.kind); |
| if let Some(f) = cb.try_load_from_on_disk_cache { |
| f(self, dep_node) |
| } |
| } |
| |
| fn with_reduced_queries<T>(self, _: impl FnOnce() -> T) -> T; |
| } |
| |
| pub trait Deps: DynSync { |
| /// Execute the operation with provided dependencies. |
| fn with_deps<OP, R>(deps: TaskDepsRef<'_>, op: OP) -> R |
| where |
| OP: FnOnce() -> R; |
| |
| /// Access dependencies from current implicit context. |
| fn read_deps<OP>(op: OP) |
| where |
| OP: for<'a> FnOnce(TaskDepsRef<'a>); |
| |
| fn name(&self, dep_kind: DepKind) -> &'static str; |
| |
| /// We use this for most things when incr. comp. is turned off. |
| const DEP_KIND_NULL: DepKind; |
| |
| /// We use this to create a forever-red node. |
| const DEP_KIND_RED: DepKind; |
| |
| /// We use this to create a side effect node. |
| const DEP_KIND_SIDE_EFFECT: DepKind; |
| |
| /// We use this to create the anon node with zero dependencies. |
| const DEP_KIND_ANON_ZERO_DEPS: DepKind; |
| |
| /// This is the highest value a `DepKind` can have. It's used during encoding to |
| /// pack information into the unused bits. |
| const DEP_KIND_MAX: u16; |
| } |
| |
| pub trait HasDepContext: Copy { |
| type Deps: self::Deps; |
| type DepContext: self::DepContext<Deps = Self::Deps>; |
| |
| fn dep_context(&self) -> &Self::DepContext; |
| } |
| |
| impl<T: DepContext> HasDepContext for T { |
| type Deps = T::Deps; |
| type DepContext = Self; |
| |
| fn dep_context(&self) -> &Self::DepContext { |
| self |
| } |
| } |
| |
| impl<T: HasDepContext, Q: Copy> HasDepContext for (T, Q) { |
| type Deps = T::Deps; |
| type DepContext = T::DepContext; |
| |
| fn dep_context(&self) -> &Self::DepContext { |
| self.0.dep_context() |
| } |
| } |
| |
| /// Describes the contents of the fingerprint generated by a given query. |
| #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
| pub enum FingerprintStyle { |
| /// The fingerprint is actually a DefPathHash. |
| DefPathHash, |
| /// The fingerprint is actually a HirId. |
| HirId, |
| /// Query key was `()` or equivalent, so fingerprint is just zero. |
| Unit, |
| /// Some opaque hash. |
| Opaque, |
| } |
| |
| impl FingerprintStyle { |
| #[inline] |
| pub const fn reconstructible(self) -> bool { |
| match self { |
| FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => { |
| true |
| } |
| FingerprintStyle::Opaque => false, |
| } |
| } |
| } |