diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 46e34462cf2..6522b1406be 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::dep_graph::DepContext; -use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects}; +use rustc_query_system::query::{QueryCache, QuerySideEffects}; use rustc_serialize::{ opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}, Decodable, Decoder, Encodable, Encoder, @@ -1056,24 +1056,24 @@ fn encode(&self, e: &mut CacheEncoder<'a, 'tcx>) { } } -pub fn encode_query_results<'a, 'tcx, CTX, Q>( - tcx: CTX, +pub fn encode_query_results<'a, 'tcx, Q>( + query: Q, + qcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) where - CTX: QueryContext + 'tcx, - Q: super::QueryConfig, + Q: super::QueryConfig>, Q::Value: Encodable>, { - let _timer = tcx - .dep_context() + let _timer = qcx + .tcx .profiler() - .verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::()); + .verbose_generic_activity_with_arg("encode_query_results_for", query.name()); - assert!(Q::query_state(tcx).all_inactive()); - let cache = Q::query_cache(tcx); + assert!(query.query_state(qcx).all_inactive()); + let cache = query.query_cache(qcx); cache.iter(&mut |key, value, dep_node| { - if Q::cache_on_disk(*tcx.dep_context(), &key) { + if query.cache_on_disk(qcx.tcx, &key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index a8592bd7086..005ce16dbb9 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -19,7 +19,7 @@ use rustc_query_system::query::{ force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, }; -use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value}; +use rustc_query_system::{LayoutOfDepth, QueryOverflow}; use rustc_serialize::Decodable; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; @@ -350,18 +350,17 @@ pub(crate) fn create_query_frame< QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash) } -fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) +fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where Q: QueryConfig>, - Q::Key: DepNodeParams>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| { panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash) }); - if Q::cache_on_disk(tcx, &key) { - let _ = Q::execute_query(tcx, key); + if query.cache_on_disk(tcx, &key) { + let _ = query.execute_query(tcx, key); } } @@ -375,11 +374,9 @@ pub(crate) fn try_load_from_disk<'tcx, V>( tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id) } -fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool +fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryConfig>, - Q::Key: DepNodeParams>, - Q::Value: Value, DepKind>, { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: @@ -403,7 +400,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); let tcx = QueryCtxt::from_tcx(tcx); - force_query::(tcx, key, dep_node); + force_query(query, tcx, key, dep_node); true } else { false @@ -412,7 +409,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx> where - Q: QueryConfig>, + Q: QueryConfig> + Default, Q::Key: DepNodeParams>, { let fingerprint_style = Q::Key::fingerprint_style(); @@ -431,8 +428,10 @@ pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> De is_anon, is_eval_always, fingerprint_style, - force_from_dep_node: Some(force_from_dep_node::), - try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::), + force_from_dep_node: Some(|tcx, dep_node| force_from_dep_node(Q::default(), tcx, dep_node)), + try_load_from_on_disk_cache: Some(|tcx, dep_node| { + try_load_from_on_disk_cache(Q::default(), tcx, dep_node) + }), } } @@ -462,44 +461,51 @@ macro_rules! define_queries { mod queries { use std::marker::PhantomData; - $(pub struct $name<'tcx> { - data: PhantomData<&'tcx ()> - })* + $( + #[derive(Copy, Clone, Default)] + pub struct $name<'tcx> { + data: PhantomData<&'tcx ()> + } + )* } $(impl<'tcx> QueryConfig> for queries::$name<'tcx> { type Key = query_keys::$name<'tcx>; type Value = query_values::$name<'tcx>; - const NAME: &'static str = stringify!($name); + + #[inline(always)] + fn name(self) -> &'static str { + stringify!($name) + } #[inline] - fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { + fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { ::rustc_middle::query::cached::$name(tcx, key) } type Cache = query_storage::$name<'tcx>; #[inline(always)] - fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState + fn query_state<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a QueryState where QueryCtxt<'tcx>: 'a { &tcx.queries.$name } #[inline(always)] - fn query_cache<'a>(tcx: QueryCtxt<'tcx>) -> &'a Self::Cache + fn query_cache<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a Self::Cache where 'tcx:'a { &tcx.query_system.caches.$name } - fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { + fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { tcx.$name(key) } #[inline] #[allow(unused_variables)] - fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { + fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { query_provided_to_value::$name( qcx.tcx, get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key) @@ -507,9 +513,13 @@ fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { } #[inline] - fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk, Self> { + fn try_load_from_disk( + self, + _qcx: QueryCtxt<'tcx>, + _key: &Self::Key + ) -> rustc_query_system::query::TryLoadFromDisk, Self::Value> { should_ever_cache_on_disk!([$($modifiers)*] { - if Self::cache_on_disk(_qcx.tcx, _key) { + if ::rustc_middle::query::cached::$name(_qcx.tcx, _key) { Some(|qcx: QueryCtxt<'tcx>, dep_node| { let value = $crate::plumbing::try_load_from_disk::>( qcx, @@ -525,15 +535,40 @@ fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_sy }) } - const ANON: bool = is_anon!([$($modifiers)*]); - const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); - const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]); - const FEEDABLE: bool = feedable!([$($modifiers)*]); + #[inline(always)] + fn anon(self) -> bool { + is_anon!([$($modifiers)*]) + } - const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name; - const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]); + #[inline(always)] + fn eval_always(self) -> bool { + is_eval_always!([$($modifiers)*]) + } - const HASH_RESULT: rustc_query_system::query::HashResult, Self> = hash_result!([$($modifiers)*]); + #[inline(always)] + fn depth_limit(self) -> bool { + depth_limit!([$($modifiers)*]) + } + + #[inline(always)] + fn feedable(self) -> bool { + feedable!([$($modifiers)*]) + } + + #[inline(always)] + fn dep_kind(self) -> rustc_middle::dep_graph::DepKind { + dep_graph::DepKind::$name + } + + #[inline(always)] + fn handle_cycle_error(self) -> rustc_query_system::HandleCycleError { + handle_cycle_error!([$($modifiers)*]) + } + + #[inline(always)] + fn hash_result(self) -> rustc_query_system::query::HashResult { + hash_result!([$($modifiers)*]) + } })* #[allow(nonstandard_style)] @@ -649,8 +684,13 @@ pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct { string_cache, ) }, - encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index| - $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index) + encode_query_results: expand_if_cached!([$($modifiers)*], |qcx, encoder, query_result_index| + $crate::on_disk_cache::encode_query_results( + super::queries::$name::default(), + qcx, + encoder, + query_result_index, + ) ), }})* } @@ -739,7 +779,13 @@ fn $name( mode: QueryMode, ) -> Option> { let qcx = QueryCtxt { tcx, queries: self }; - get_query::, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode) + get_query( + queries::$name::default(), + qcx, + span, + key, + mode + ) })* } }; diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 6969f2dbef8..ba83b775631 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -88,6 +88,15 @@ fn dep_context(&self) -> &Self::DepContext { } } +impl HasDepContext for (T, Q) { + type DepKind = T::DepKind; + 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 { diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 4b3cd16c29f..5f554a54dea 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -16,12 +16,9 @@ pub trait CacheSelector<'tcx, V> { V: Copy; } -pub trait QueryStorage { - type Value: Copy; -} - -pub trait QueryCache: QueryStorage + Sized { +pub trait QueryCache: Sized { type Key: Hash + Eq + Copy + Debug; + type Value: Copy + Debug; /// Checks if the query is already computed and in the cache. /// It returns the shard index and a lock guard to the shard, @@ -55,16 +52,13 @@ fn default() -> Self { } } -impl QueryStorage for DefaultCache { - type Value = V; -} - impl QueryCache for DefaultCache where K: Eq + Hash + Copy + Debug, V: Copy + Debug, { type Key = K; + type Value = V; #[inline(always)] fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { @@ -127,15 +121,12 @@ fn default() -> Self { } } -impl QueryStorage for SingleCache { - type Value = V; -} - impl QueryCache for SingleCache where V: Copy + Debug, { type Key = (); + type Value = V; #[inline(always)] fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> { @@ -173,16 +164,13 @@ fn default() -> Self { } } -impl QueryStorage for VecCache { - type Value = V; -} - impl QueryCache for VecCache where K: Eq + Idx + Copy + Debug, V: Copy + Debug, { type Key = K; + type Value = V; #[inline(always)] fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> { diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index d5637387346..e44a00ca6cb 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -10,14 +10,12 @@ use std::fmt::Debug; use std::hash::Hash; -pub type HashResult = - Option, &>::Value) -> Fingerprint>; +pub type HashResult = Option, &V) -> Fingerprint>; -pub type TryLoadFromDisk = - Option Option<>::Value>>; +pub type TryLoadFromDisk = Option Option>; -pub trait QueryConfig { - const NAME: &'static str; +pub trait QueryConfig: Copy { + fn name(self) -> &'static str; // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, // but it isn't necessary. @@ -27,36 +25,35 @@ pub trait QueryConfig { type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: Qcx) -> &'a QueryState + fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState where Qcx: 'a; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(tcx: Qcx) -> &'a Self::Cache + fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache where Qcx: 'a; - fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool; + fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Value; + fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value; - fn compute(tcx: Qcx, key: Self::Key) -> Self::Value; + fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value; - fn try_load_from_disk(qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk; + fn try_load_from_disk(self, qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk; - const ANON: bool; - const EVAL_ALWAYS: bool; - const DEPTH_LIMIT: bool; - const FEEDABLE: bool; + fn anon(self) -> bool; + fn eval_always(self) -> bool; + fn depth_limit(self) -> bool; + fn feedable(self) -> bool; - const DEP_KIND: Qcx::DepKind; - const HANDLE_CYCLE_ERROR: HandleCycleError; - - const HASH_RESULT: HashResult; + fn dep_kind(self) -> Qcx::DepKind; + fn handle_cycle_error(self) -> HandleCycleError; + fn hash_result(self) -> HashResult; // Just here for convernience and checking that the key matches the kind, don't override this. - fn construct_dep_node(tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { - DepNode::construct(tcx, Self::DEP_KIND, key) + fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { + DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 383c63cd2f8..312b0e1688d 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -8,8 +8,7 @@ mod caches; pub use self::caches::{ - CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage, SingleCacheSelector, - VecCacheSelector, + CacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, VecCacheSelector, }; mod config; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 5f003fa70e1..005fcd8c4cc 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,6 +2,7 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. +use crate::dep_graph::HasDepContext; use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; @@ -126,7 +127,7 @@ fn mk_cycle( handler: HandleCycleError, ) -> R where - Qcx: QueryContext + crate::query::HasDepContext, + Qcx: QueryContext + HasDepContext, R: std::fmt::Debug + Value, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); @@ -181,7 +182,7 @@ fn try_start<'b, Qcx>( key: K, ) -> TryGetJob<'b, K, D> where - Qcx: QueryContext + crate::query::HasDepContext, + Qcx: QueryContext + HasDepContext, { #[cfg(parallel_compiler)] let mut state_lock = state.active.get_shard_by_value(&key).lock(); @@ -350,6 +351,7 @@ pub fn try_get_cached(tcx: Tcx, cache: &C, key: &C::Key) -> Option( + query: Q, qcx: Qcx, span: Span, key: Q::Key, @@ -359,12 +361,12 @@ fn try_execute_query( Q: QueryConfig, Qcx: QueryContext, { - let state = Q::query_state(qcx); + let state = query.query_state(qcx); match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job::(qcx, key, dep_node, job.id); - let cache = Q::query_cache(qcx); - if Q::FEEDABLE { + let (result, dep_node_index) = execute_job(query, qcx, key.clone(), dep_node, job.id); + let cache = query.query_cache(qcx); + if query.feedable() { // We should not compute queries that also got a value via feeding. // This can't happen, as query feeding adds the very dependencies to the fed query // as its feeding query had. So if the fed query is red, so is its feeder, which will @@ -379,12 +381,12 @@ fn try_execute_query( (result, Some(dep_node_index)) } TryGetJob::Cycle(error) => { - let result = mk_cycle(qcx, error, Q::HANDLE_CYCLE_ERROR); + let result = mk_cycle(qcx, error, query.handle_cycle_error()); (result, None) } #[cfg(parallel_compiler)] TryGetJob::JobCompleted(query_blocked_prof_timer) => { - let Some((v, index)) = Q::query_cache(qcx).lookup(&key) else { + let Some((v, index)) = query.query_cache(qcx).lookup(&key) else { panic!("value must be in cache after waiting") }; @@ -398,6 +400,7 @@ fn try_execute_query( #[inline(always)] fn execute_job( + query: Q, qcx: Qcx, key: Q::Key, mut dep_node_opt: Option>, @@ -418,14 +421,14 @@ fn execute_job( } let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || Q::compute(qcx, key)); + let result = qcx.start_query(job_id, query.depth_limit(), None, || query.compute(qcx, key)); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); // Similarly, fingerprint the result to assert that // it doesn't have anything not considered hashable. if cfg!(debug_assertions) - && let Some(hash_result) = Q::HASH_RESULT + && let Some(hash_result) = query.hash_result() { qcx.dep_context().with_stable_hashing_context(|mut hcx| { hash_result(&mut hcx, &result); @@ -435,15 +438,15 @@ fn execute_job( return (result, dep_node_index); } - if !Q::ANON && !Q::EVAL_ALWAYS { + if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.get_or_insert_with(|| Q::construct_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.get_or_insert_with(|| query.construct_dep_node(*qcx.dep_context(), &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. if let Some(ret) = qcx.start_query(job_id, false, None, || { - try_load_from_disk_and_cache_in_memory::(qcx, &key, &dep_node) + try_load_from_disk_and_cache_in_memory(query, qcx, &key, &dep_node) }) { return ret; } @@ -453,17 +456,24 @@ fn execute_job( let diagnostics = Lock::new(ThinVec::new()); let (result, dep_node_index) = - qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || { - if Q::ANON { - return dep_graph - .with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || Q::compute(qcx, key)); + qcx.start_query(job_id, query.depth_limit(), Some(&diagnostics), || { + if query.anon() { + return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind(), || { + query.compute(qcx, key) + }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.unwrap_or_else(|| Q::construct_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); - dep_graph.with_task(dep_node, qcx, key, Q::compute, Q::HASH_RESULT) + dep_graph.with_task( + dep_node, + (qcx, query), + key, + |(qcx, query), key| query.compute(qcx, key), + query.hash_result(), + ) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -472,7 +482,7 @@ fn execute_job( let side_effects = QuerySideEffects { diagnostics }; if std::intrinsics::unlikely(!side_effects.is_empty()) { - if Q::ANON { + if query.anon() { qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { qcx.store_side_effects(dep_node_index, side_effects); @@ -484,6 +494,7 @@ fn execute_job( #[inline(always)] fn try_load_from_disk_and_cache_in_memory( + query: Q, qcx: Qcx, key: &Q::Key, dep_node: &DepNode, @@ -502,7 +513,7 @@ fn try_load_from_disk_and_cache_in_memory( // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if let Some(try_load_from_disk) = Q::try_load_from_disk(qcx, &key) { + if let Some(try_load_from_disk) = query.try_load_from_disk(qcx, &key) { let prof_timer = qcx.dep_context().profiler().incr_cache_loading(); // The call to `with_query_deserialization` enforces that no new `DepNodes` @@ -536,7 +547,7 @@ fn try_load_from_disk_and_cache_in_memory( if std::intrinsics::unlikely( try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, ) { - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result()); } return Some((result, dep_node_index)); @@ -555,7 +566,7 @@ fn try_load_from_disk_and_cache_in_memory( let prof_timer = qcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| Q::compute(qcx, *key)); + let result = dep_graph.with_ignore(|| query.compute(qcx, *key)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -568,7 +579,7 @@ fn try_load_from_disk_and_cache_in_memory( // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result()); Some((result, dep_node_index)) } @@ -689,19 +700,23 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run(qcx: Qcx, key: &Q::Key) -> (bool, Option>) +fn ensure_must_run( + query: Q, + qcx: Qcx, + key: &Q::Key, +) -> (bool, Option>) where Q: QueryConfig, Qcx: QueryContext, { - if Q::EVAL_ALWAYS { + if query.eval_always() { return (true, None); } // Ensuring an anonymous query makes no sense - assert!(!Q::ANON); + assert!(!query.anon()); - let dep_node = Q::construct_dep_node(*qcx.dep_context(), key); + let dep_node = query.construct_dep_node(*qcx.dep_context(), key); let dep_graph = qcx.dep_context().dep_graph(); match dep_graph.try_mark_green(qcx, &dep_node) { @@ -729,15 +744,19 @@ pub enum QueryMode { } #[inline(always)] -pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option +pub fn get_query( + query: Q, + qcx: Qcx, + span: Span, + key: Q::Key, + mode: QueryMode, +) -> Option where - D: DepKind, Q: QueryConfig, - Q::Value: Value, Qcx: QueryContext, { let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run::(qcx, &key); + let (must_run, dep_node) = ensure_must_run(query, qcx, &key); if !must_run { return None; } @@ -747,28 +766,30 @@ pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) }; let (result, dep_node_index) = - ensure_sufficient_stack(|| try_execute_query::(qcx, span, key, dep_node)); + ensure_sufficient_stack(|| try_execute_query(query, qcx, span, key, dep_node)); if let Some(dep_node_index) = dep_node_index { qcx.dep_context().dep_graph().read_index(dep_node_index) } Some(result) } -pub fn force_query(qcx: Qcx, key: Q::Key, dep_node: DepNode) -where - D: DepKind, +pub fn force_query( + query: Q, + qcx: Qcx, + key: Q::Key, + dep_node: DepNode<::DepKind>, +) where Q: QueryConfig, - Q::Value: Value, Qcx: QueryContext, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - if let Some((_, index)) = Q::query_cache(qcx).lookup(&key) { + if let Some((_, index)) = query.query_cache(qcx).lookup(&key) { qcx.dep_context().profiler().query_cache_hit(index.into()); return; } - debug_assert!(!Q::ANON); + debug_assert!(!query.anon()); - ensure_sufficient_stack(|| try_execute_query::(qcx, DUMMY_SP, key, Some(dep_node))); + ensure_sufficient_stack(|| try_execute_query(query, qcx, DUMMY_SP, key, Some(dep_node))); }