| 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())) |
| } |