blob: 9787a998d63718514eef6c666971816aef5a5838 [file]
use std::panic;
use tracing::instrument;
pub use self::dep_node::{
DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label, label_strs,
};
pub use self::dep_node_key::DepNodeKey;
pub use self::graph::{
DepGraph, DepGraphData, DepNodeIndex, QuerySideEffect, TaskDepsRef, WorkProduct,
WorkProductMap, hash_result,
};
use self::graph::{MarkFrame, print_markframe_trace};
pub use self::retained::RetainedDepGraph;
pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
pub use crate::dep_graph::debug::{DepNodeFilter, EdgeFilter};
use crate::ty::print::with_reduced_queries;
use crate::ty::{self, TyCtxt};
mod debug;
pub(crate) mod dep_node;
mod dep_node_key;
mod edges;
mod graph;
mod retained;
mod serialized;
/// Describes the contents of the fingerprint generated by a given query.
///
/// This is mainly for determining whether and how we can reconstruct a key
/// from the fingerprint.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum KeyFingerprintStyle {
/// 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,
/// The fingerprint is an opaque hash, and a key cannot be reconstructed from it.
Opaque,
}
impl KeyFingerprintStyle {
/// True if a key can _potentially_ be recovered from a key fingerprint
/// with this style.
///
/// For some key types, recovery is possible but not guaranteed.
#[inline]
pub const fn is_maybe_recoverable(self) -> bool {
match self {
KeyFingerprintStyle::DefPathHash
| KeyFingerprintStyle::Unit
| KeyFingerprintStyle::HirId => true,
KeyFingerprintStyle::Opaque => false,
}
}
}
/// Execute the operation with provided dependencies.
fn with_deps<OP, R>(task_deps: TaskDepsRef<'_>, op: OP) -> R
where
OP: FnOnce() -> R,
{
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt { task_deps, ..*icx };
ty::tls::enter_context(&icx, op)
})
}
/// Access dependencies from current implicit context.
fn read_deps<OP>(op: OP)
where
OP: for<'a> FnOnce(TaskDepsRef<'a>),
{
ty::tls::with_context_opt(|icx| {
let Some(icx) = icx else { return };
op(icx.task_deps)
})
}
impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn dep_kind_vtable(self, dk: DepKind) -> &'tcx DepKindVTable<'tcx> {
&self.dep_kind_vtables[dk.as_usize()]
}
fn with_reduced_queries<T>(self, f: impl FnOnce() -> T) -> T {
with_reduced_queries!(f())
}
#[inline(always)]
pub fn key_fingerprint_style(self, kind: DepKind) -> KeyFingerprintStyle {
self.dep_kind_vtable(kind).key_fingerprint_style
}
/// 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: &MarkFrame<'_>,
) -> bool {
if let Some(force_fn) = self.dep_kind_vtable(dep_node.kind).force_from_dep_node_fn {
match panic::catch_unwind(panic::AssertUnwindSafe(|| {
force_fn(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
}
}
}