blob: 3bc2e35b02bcd3910948be909d21fcd78a97a805 [file] [log] [blame] [edit]
use rustc_middle::arena::Arena;
use rustc_middle::bug;
use rustc_middle::dep_graph::{DepKindVTable, DepNodeKey, KeyFingerprintStyle};
use rustc_middle::query::QueryCache;
use crate::GetQueryVTable;
use crate::plumbing::{force_from_dep_node_inner, promote_from_disk_inner};
/// [`DepKindVTable`] constructors for special dep kinds that aren't queries.
#[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")]
mod non_query {
use super::*;
// We use this for most things when incr. comp. is turned off.
pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|_, dep_node, _| {
bug!("force_from_dep_node: encountered {dep_node:?}")
}),
promote_from_disk_fn: None,
}
}
// We use this for the forever-red node.
pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|_, dep_node, _| {
bug!("force_from_dep_node: encountered {dep_node:?}")
}),
promote_from_disk_fn: None,
}
}
pub(crate) fn SideEffect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: Some(|tcx, _, prev_index| {
tcx.dep_graph.force_side_effect(tcx, prev_index);
true
}),
promote_from_disk_fn: None,
}
}
pub(crate) fn AnonZeroDeps<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: Some(|_, _, _| bug!("cannot force an anon node")),
promote_from_disk_fn: None,
}
}
pub(crate) fn TraitSelect<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: None,
promote_from_disk_fn: None,
}
}
pub(crate) fn CompileCodegenUnit<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: None,
promote_from_disk_fn: None,
}
}
pub(crate) fn CompileMonoItem<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Opaque,
force_from_dep_node_fn: None,
promote_from_disk_fn: None,
}
}
pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
DepKindVTable {
is_eval_always: false,
key_fingerprint_style: KeyFingerprintStyle::Unit,
force_from_dep_node_fn: None,
promote_from_disk_fn: None,
}
}
}
/// Shared implementation of the [`DepKindVTable`] constructor for queries.
/// Called from macro-generated code for each query.
pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
is_anon: bool,
is_cache_on_disk: bool,
is_eval_always: bool,
) -> DepKindVTable<'tcx>
where
Q: GetQueryVTable<'tcx>,
{
let key_fingerprint_style = if is_anon {
KeyFingerprintStyle::Opaque
} else {
<Q::Cache as QueryCache>::Key::key_fingerprint_style()
};
// A query dep-node can only be forced or promoted if it can recover a key
// from its key fingerprint.
let can_recover = key_fingerprint_style.is_maybe_recoverable();
if is_anon {
assert!(!can_recover);
}
DepKindVTable {
is_eval_always,
key_fingerprint_style,
force_from_dep_node_fn: can_recover.then_some(force_from_dep_node_inner::<Q>),
promote_from_disk_fn: (can_recover && is_cache_on_disk)
.then_some(promote_from_disk_inner::<Q>),
}
}
macro_rules! define_dep_kind_vtables {
(
queries {
$(
$(#[$attr:meta])*
fn $name:ident($K:ty) -> $V:ty
{
// Search for (QMODLIST) to find all occurrences of this query modifier list.
anon: $anon:literal,
arena_cache: $arena_cache:literal,
cache_on_disk: $cache_on_disk:literal,
cycle_error_handling: $cycle_error_handling:ident,
depth_limit: $depth_limit:literal,
eval_always: $eval_always:literal,
feedable: $feedable:literal,
no_hash: $no_hash:literal,
returns_error_guaranteed: $returns_error_guaranteed:literal,
separate_provide_extern: $separate_provide_extern:literal,
}
)*
}
non_queries {
$(
$(#[$nq_attr:meta])*
$nq_name:ident,
)*
}
) => {{
// The small number of non-query vtables: `Null`, `Red`, etc.
let nq_vtables = [
$(
non_query::$nq_name(),
)*
];
// The large number of query vtables.
let q_vtables: [DepKindVTable<'tcx>; _] = [
$(
$crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
$crate::query_impl::$name::VTableGetter,
>(
$anon,
$cache_on_disk,
$eval_always,
)
),*
];
(nq_vtables, q_vtables)
}}
}
// Create an array of vtables, one for each dep kind (non-query and query).
pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
let (nq_vtables, q_vtables) =
rustc_middle::rustc_with_all_queries! { define_dep_kind_vtables! };
// Non-query vtables must come before query vtables, to match the order of `DepKind`.
arena.alloc_from_iter(nq_vtables.into_iter().chain(q_vtables.into_iter()))
}