Make rustc_query_system
take QueryConfig
by instance.
This commit is contained in:
parent
d962ea5789
commit
3fd7c4a17d
6 changed files with 184 additions and 125 deletions
|
@ -13,7 +13,7 @@ use rustc_middle::mir::{self, interpret};
|
||||||
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
|
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_query_system::dep_graph::DepContext;
|
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::{
|
use rustc_serialize::{
|
||||||
opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
|
opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
|
||||||
Decodable, Decoder, Encodable, Encoder,
|
Decodable, Decoder, Encodable, Encoder,
|
||||||
|
@ -1056,24 +1056,24 @@ impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for [u8] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_query_results<'a, 'tcx, CTX, Q>(
|
pub fn encode_query_results<'a, 'tcx, Q>(
|
||||||
tcx: CTX,
|
query: Q,
|
||||||
|
qcx: QueryCtxt<'tcx>,
|
||||||
encoder: &mut CacheEncoder<'a, 'tcx>,
|
encoder: &mut CacheEncoder<'a, 'tcx>,
|
||||||
query_result_index: &mut EncodedDepNodeIndex,
|
query_result_index: &mut EncodedDepNodeIndex,
|
||||||
) where
|
) where
|
||||||
CTX: QueryContext + 'tcx,
|
Q: super::QueryConfig<QueryCtxt<'tcx>>,
|
||||||
Q: super::QueryConfig<CTX>,
|
|
||||||
Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
|
Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
|
||||||
{
|
{
|
||||||
let _timer = tcx
|
let _timer = qcx
|
||||||
.dep_context()
|
.tcx
|
||||||
.profiler()
|
.profiler()
|
||||||
.verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::<Q>());
|
.verbose_generic_activity_with_arg("encode_query_results_for", query.name());
|
||||||
|
|
||||||
assert!(Q::query_state(tcx).all_inactive());
|
assert!(query.query_state(qcx).all_inactive());
|
||||||
let cache = Q::query_cache(tcx);
|
let cache = query.query_cache(qcx);
|
||||||
cache.iter(&mut |key, value, dep_node| {
|
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());
|
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
|
||||||
|
|
||||||
// Record position of the cache entry.
|
// Record position of the cache entry.
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_query_system::query::{
|
use rustc_query_system::query::{
|
||||||
force_query, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
|
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_serialize::Decodable;
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
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)
|
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
|
where
|
||||||
Q: QueryConfig<QueryCtxt<'tcx>>,
|
Q: QueryConfig<QueryCtxt<'tcx>>,
|
||||||
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
|
|
||||||
{
|
{
|
||||||
debug_assert!(tcx.dep_graph.is_green(&dep_node));
|
debug_assert!(tcx.dep_graph.is_green(&dep_node));
|
||||||
|
|
||||||
let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
|
let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| {
|
||||||
panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
|
panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash)
|
||||||
});
|
});
|
||||||
if Q::cache_on_disk(tcx, &key) {
|
if query.cache_on_disk(tcx, &key) {
|
||||||
let _ = Q::execute_query(tcx, key);
|
let _ = query.execute_query(tcx, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,11 +374,9 @@ where
|
||||||
tcx.on_disk_cache().as_ref()?.try_load_query_result(*tcx, id)
|
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
|
where
|
||||||
Q: QueryConfig<QueryCtxt<'tcx>>,
|
Q: QueryConfig<QueryCtxt<'tcx>>,
|
||||||
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
|
|
||||||
Q::Value: Value<TyCtxt<'tcx>, DepKind>,
|
|
||||||
{
|
{
|
||||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||||
// `DepNode::codegen_unit`:
|
// `DepNode::codegen_unit`:
|
||||||
|
@ -403,7 +400,7 @@ where
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
|
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
|
||||||
let tcx = QueryCtxt::from_tcx(tcx);
|
let tcx = QueryCtxt::from_tcx(tcx);
|
||||||
force_query::<Q, _, DepKind>(tcx, key, dep_node);
|
force_query(query, tcx, key, dep_node);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -412,7 +409,7 @@ where
|
||||||
|
|
||||||
pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
|
pub(crate) fn query_callback<'tcx, Q>(is_anon: bool, is_eval_always: bool) -> DepKindStruct<'tcx>
|
||||||
where
|
where
|
||||||
Q: QueryConfig<QueryCtxt<'tcx>>,
|
Q: QueryConfig<QueryCtxt<'tcx>> + Default,
|
||||||
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
|
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
|
||||||
{
|
{
|
||||||
let fingerprint_style = Q::Key::fingerprint_style();
|
let fingerprint_style = Q::Key::fingerprint_style();
|
||||||
|
@ -431,8 +428,10 @@ where
|
||||||
is_anon,
|
is_anon,
|
||||||
is_eval_always,
|
is_eval_always,
|
||||||
fingerprint_style,
|
fingerprint_style,
|
||||||
force_from_dep_node: Some(force_from_dep_node::<Q>),
|
force_from_dep_node: Some(|tcx, dep_node| force_from_dep_node(Q::default(), tcx, dep_node)),
|
||||||
try_load_from_on_disk_cache: Some(try_load_from_on_disk_cache::<Q>),
|
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
|
||||||
|
try_load_from_on_disk_cache(Q::default(), tcx, dep_node)
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,44 +461,59 @@ macro_rules! define_queries {
|
||||||
mod queries {
|
mod queries {
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
$(pub struct $name<'tcx> {
|
$(
|
||||||
data: PhantomData<&'tcx ()>
|
#[derive(Copy, Clone, Debug)]
|
||||||
})*
|
pub struct $name<'tcx> {
|
||||||
|
data: PhantomData<&'tcx ()>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for $name<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
data: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
|
$(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
|
||||||
type Key = query_keys::$name<'tcx>;
|
type Key = query_keys::$name<'tcx>;
|
||||||
type Value = query_values::$name<'tcx>;
|
type Value = query_values::$name<'tcx>;
|
||||||
const NAME: &'static str = stringify!($name);
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn name(self) -> &'static str {
|
||||||
|
stringify!($name)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
::rustc_middle::query::cached::$name(tcx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Cache = query_storage::$name<'tcx>;
|
type Cache = query_storage::$name<'tcx>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
|
fn query_state<'a>(self, tcx: QueryCtxt<'tcx>) -> &'a QueryState<Self::Key, crate::dep_graph::DepKind>
|
||||||
where QueryCtxt<'tcx>: 'a
|
where QueryCtxt<'tcx>: 'a
|
||||||
{
|
{
|
||||||
&tcx.queries.$name
|
&tcx.queries.$name
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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
|
where 'tcx:'a
|
||||||
{
|
{
|
||||||
&tcx.query_system.caches.$name
|
&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)
|
tcx.$name(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[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(
|
query_provided_to_value::$name(
|
||||||
qcx.tcx,
|
qcx.tcx,
|
||||||
get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
|
get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
|
||||||
|
@ -507,9 +521,13 @@ macro_rules! define_queries {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
|
fn try_load_from_disk(
|
||||||
|
self,
|
||||||
|
_qcx: QueryCtxt<'tcx>,
|
||||||
|
_key: &Self::Key
|
||||||
|
) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self::Value> {
|
||||||
should_ever_cache_on_disk!([$($modifiers)*] {
|
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| {
|
Some(|qcx: QueryCtxt<'tcx>, dep_node| {
|
||||||
let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
|
let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
|
||||||
qcx,
|
qcx,
|
||||||
|
@ -525,15 +543,40 @@ macro_rules! define_queries {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const ANON: bool = is_anon!([$($modifiers)*]);
|
#[inline(always)]
|
||||||
const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
|
fn anon(self) -> bool {
|
||||||
const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]);
|
is_anon!([$($modifiers)*])
|
||||||
const FEEDABLE: bool = feedable!([$($modifiers)*]);
|
}
|
||||||
|
|
||||||
const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name;
|
#[inline(always)]
|
||||||
const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]);
|
fn eval_always(self) -> bool {
|
||||||
|
is_eval_always!([$($modifiers)*])
|
||||||
|
}
|
||||||
|
|
||||||
const HASH_RESULT: rustc_query_system::query::HashResult<QueryCtxt<'tcx>, 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<Self::Value> {
|
||||||
|
hash_result!([$($modifiers)*])
|
||||||
|
}
|
||||||
})*
|
})*
|
||||||
|
|
||||||
#[allow(nonstandard_style)]
|
#[allow(nonstandard_style)]
|
||||||
|
@ -649,8 +692,13 @@ macro_rules! define_queries {
|
||||||
string_cache,
|
string_cache,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
encode_query_results: expand_if_cached!([$($modifiers)*], |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<'_>>(tcx, encoder, query_result_index)
|
$crate::on_disk_cache::encode_query_results(
|
||||||
|
super::queries::$name::default(),
|
||||||
|
qcx,
|
||||||
|
encoder,
|
||||||
|
query_result_index,
|
||||||
|
)
|
||||||
),
|
),
|
||||||
}})*
|
}})*
|
||||||
}
|
}
|
||||||
|
@ -739,7 +787,13 @@ macro_rules! define_queries_struct {
|
||||||
mode: QueryMode,
|
mode: QueryMode,
|
||||||
) -> Option<query_values::$name<'tcx>> {
|
) -> Option<query_values::$name<'tcx>> {
|
||||||
let qcx = QueryCtxt { tcx, queries: self };
|
let qcx = QueryCtxt { tcx, queries: self };
|
||||||
get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)
|
get_query(
|
||||||
|
queries::$name::default(),
|
||||||
|
qcx,
|
||||||
|
span,
|
||||||
|
key,
|
||||||
|
mode
|
||||||
|
)
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,12 +16,9 @@ pub trait CacheSelector<'tcx, V> {
|
||||||
V: Copy;
|
V: Copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QueryStorage {
|
pub trait QueryCache: Sized {
|
||||||
type Value: Copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait QueryCache: QueryStorage + Sized {
|
|
||||||
type Key: Hash + Eq + Copy + Debug;
|
type Key: Hash + Eq + Copy + Debug;
|
||||||
|
type Value: Copy + Debug;
|
||||||
|
|
||||||
/// Checks if the query is already computed and in the cache.
|
/// Checks if the query is already computed and in the cache.
|
||||||
/// It returns the shard index and a lock guard to the shard,
|
/// It returns the shard index and a lock guard to the shard,
|
||||||
|
@ -55,16 +52,13 @@ impl<K, V> Default for DefaultCache<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Eq + Hash, V: Copy + Debug> QueryStorage for DefaultCache<K, V> {
|
|
||||||
type Value = V;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> QueryCache for DefaultCache<K, V>
|
impl<K, V> QueryCache for DefaultCache<K, V>
|
||||||
where
|
where
|
||||||
K: Eq + Hash + Copy + Debug,
|
K: Eq + Hash + Copy + Debug,
|
||||||
V: Copy + Debug,
|
V: Copy + Debug,
|
||||||
{
|
{
|
||||||
type Key = K;
|
type Key = K;
|
||||||
|
type Value = V;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
||||||
|
@ -127,15 +121,12 @@ impl<V> Default for SingleCache<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Copy + Debug> QueryStorage for SingleCache<V> {
|
|
||||||
type Value = V;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> QueryCache for SingleCache<V>
|
impl<V> QueryCache for SingleCache<V>
|
||||||
where
|
where
|
||||||
V: Copy + Debug,
|
V: Copy + Debug,
|
||||||
{
|
{
|
||||||
type Key = ();
|
type Key = ();
|
||||||
|
type Value = V;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> {
|
fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> {
|
||||||
|
@ -173,16 +164,13 @@ impl<K: Idx, V> Default for VecCache<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Eq + Idx, V: Copy + Debug> QueryStorage for VecCache<K, V> {
|
|
||||||
type Value = V;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V> QueryCache for VecCache<K, V>
|
impl<K, V> QueryCache for VecCache<K, V>
|
||||||
where
|
where
|
||||||
K: Eq + Idx + Copy + Debug,
|
K: Eq + Idx + Copy + Debug,
|
||||||
V: Copy + Debug,
|
V: Copy + Debug,
|
||||||
{
|
{
|
||||||
type Key = K;
|
type Key = K;
|
||||||
|
type Value = V;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
|
||||||
|
|
|
@ -10,14 +10,12 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
pub type HashResult<Qcx, Q> =
|
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
|
||||||
Option<fn(&mut StableHashingContext<'_>, &<Q as QueryConfig<Qcx>>::Value) -> Fingerprint>;
|
|
||||||
|
|
||||||
pub type TryLoadFromDisk<Qcx, Q> =
|
pub type TryLoadFromDisk<Qcx, V> = Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>;
|
||||||
Option<fn(Qcx, SerializedDepNodeIndex) -> Option<<Q as QueryConfig<Qcx>>::Value>>;
|
|
||||||
|
|
||||||
pub trait QueryConfig<Qcx: QueryContext> {
|
pub trait QueryConfig<Qcx: QueryContext>: Copy + Debug {
|
||||||
const NAME: &'static str;
|
fn name(self) -> &'static str;
|
||||||
|
|
||||||
// `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
|
// `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
|
||||||
// but it isn't necessary.
|
// but it isn't necessary.
|
||||||
|
@ -27,36 +25,35 @@ pub trait QueryConfig<Qcx: QueryContext> {
|
||||||
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
|
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
|
||||||
|
|
||||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||||
fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::DepKind>
|
fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::DepKind>
|
||||||
where
|
where
|
||||||
Qcx: 'a;
|
Qcx: 'a;
|
||||||
|
|
||||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
// 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
|
where
|
||||||
Qcx: 'a;
|
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
|
// 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<Qcx, Self>;
|
fn try_load_from_disk(self, qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self::Value>;
|
||||||
|
|
||||||
const ANON: bool;
|
fn anon(self) -> bool;
|
||||||
const EVAL_ALWAYS: bool;
|
fn eval_always(self) -> bool;
|
||||||
const DEPTH_LIMIT: bool;
|
fn depth_limit(self) -> bool;
|
||||||
const FEEDABLE: bool;
|
fn feedable(self) -> bool;
|
||||||
|
|
||||||
const DEP_KIND: Qcx::DepKind;
|
fn dep_kind(self) -> Qcx::DepKind;
|
||||||
const HANDLE_CYCLE_ERROR: HandleCycleError;
|
fn handle_cycle_error(self) -> HandleCycleError;
|
||||||
|
fn hash_result(self) -> HashResult<Self::Value>;
|
||||||
const HASH_RESULT: HashResult<Qcx, Self>;
|
|
||||||
|
|
||||||
// Just here for convernience and checking that the key matches the kind, don't override this.
|
// 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<Qcx::DepKind> {
|
fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode<Qcx::DepKind> {
|
||||||
DepNode::construct(tcx, Self::DEP_KIND, key)
|
DepNode::construct(tcx, self.dep_kind(), key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ pub use self::job::{print_query_stack, QueryInfo, QueryJob, QueryJobId, QueryJob
|
||||||
|
|
||||||
mod caches;
|
mod caches;
|
||||||
pub use self::caches::{
|
pub use self::caches::{
|
||||||
CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage, SingleCacheSelector,
|
CacheSelector, DefaultCacheSelector, QueryCache, SingleCacheSelector, VecCacheSelector,
|
||||||
VecCacheSelector,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
//! generate the actual methods on tcx which find and execute the provider,
|
//! generate the actual methods on tcx which find and execute the provider,
|
||||||
//! manage the caches, and so forth.
|
//! manage the caches, and so forth.
|
||||||
|
|
||||||
|
use crate::dep_graph::HasDepContext;
|
||||||
use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
|
use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
|
||||||
use crate::ich::StableHashingContext;
|
use crate::ich::StableHashingContext;
|
||||||
use crate::query::caches::QueryCache;
|
use crate::query::caches::QueryCache;
|
||||||
|
@ -127,7 +128,7 @@ fn mk_cycle<Qcx, R, D: DepKind>(
|
||||||
handler: HandleCycleError,
|
handler: HandleCycleError,
|
||||||
) -> R
|
) -> R
|
||||||
where
|
where
|
||||||
Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
|
Qcx: QueryContext + HasDepContext<DepKind = D>,
|
||||||
R: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
|
R: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
|
||||||
{
|
{
|
||||||
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
||||||
|
@ -182,7 +183,7 @@ where
|
||||||
key: K,
|
key: K,
|
||||||
) -> TryGetJob<'b, K, D>
|
) -> TryGetJob<'b, K, D>
|
||||||
where
|
where
|
||||||
Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
|
Qcx: QueryContext + HasDepContext<DepKind = D>,
|
||||||
{
|
{
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
let mut state_lock = state.active.get_shard_by_value(&key).lock();
|
let mut state_lock = state.active.get_shard_by_value(&key).lock();
|
||||||
|
@ -349,6 +350,7 @@ where
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn try_execute_query<Q, Qcx>(
|
fn try_execute_query<Q, Qcx>(
|
||||||
|
query: Q,
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
span: Span,
|
span: Span,
|
||||||
key: Q::Key,
|
key: Q::Key,
|
||||||
|
@ -358,12 +360,12 @@ where
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Qcx: QueryContext,
|
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) {
|
match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key) {
|
||||||
TryGetJob::NotYetStarted(job) => {
|
TryGetJob::NotYetStarted(job) => {
|
||||||
let (result, dep_node_index) = execute_job::<Q, Qcx>(qcx, key, dep_node, job.id);
|
let (result, dep_node_index) = execute_job(query, qcx, key.clone(), dep_node, job.id);
|
||||||
let cache = Q::query_cache(qcx);
|
let cache = query.query_cache(qcx);
|
||||||
if Q::FEEDABLE {
|
if query.feedable() {
|
||||||
// We should not compute queries that also got a value via feeding.
|
// 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
|
// 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
|
// as its feeding query had. So if the fed query is red, so is its feeder, which will
|
||||||
|
@ -378,12 +380,12 @@ where
|
||||||
(result, Some(dep_node_index))
|
(result, Some(dep_node_index))
|
||||||
}
|
}
|
||||||
TryGetJob::Cycle(error) => {
|
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)
|
(result, None)
|
||||||
}
|
}
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
TryGetJob::JobCompleted(query_blocked_prof_timer) => {
|
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")
|
panic!("value must be in cache after waiting")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -397,6 +399,7 @@ where
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn execute_job<Q, Qcx>(
|
fn execute_job<Q, Qcx>(
|
||||||
|
query: Q,
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
key: Q::Key,
|
key: Q::Key,
|
||||||
mut dep_node_opt: Option<DepNode<Qcx::DepKind>>,
|
mut dep_node_opt: Option<DepNode<Qcx::DepKind>>,
|
||||||
|
@ -417,14 +420,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let prof_timer = qcx.dep_context().profiler().query_provider();
|
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();
|
let dep_node_index = dep_graph.next_virtual_depnode_index();
|
||||||
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
||||||
|
|
||||||
// Similarly, fingerprint the result to assert that
|
// Similarly, fingerprint the result to assert that
|
||||||
// it doesn't have anything not considered hashable.
|
// it doesn't have anything not considered hashable.
|
||||||
if cfg!(debug_assertions)
|
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| {
|
qcx.dep_context().with_stable_hashing_context(|mut hcx| {
|
||||||
hash_result(&mut hcx, &result);
|
hash_result(&mut hcx, &result);
|
||||||
|
@ -434,15 +437,15 @@ where
|
||||||
return (result, dep_node_index);
|
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.
|
// `to_dep_node` is expensive for some `DepKind`s.
|
||||||
let dep_node =
|
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
|
// The diagnostics for this query will be promoted to the current session during
|
||||||
// `try_mark_green()`, so we can ignore them here.
|
// `try_mark_green()`, so we can ignore them here.
|
||||||
if let Some(ret) = qcx.start_query(job_id, false, None, || {
|
if let Some(ret) = qcx.start_query(job_id, false, None, || {
|
||||||
try_load_from_disk_and_cache_in_memory::<Q, Qcx>(qcx, &key, &dep_node)
|
try_load_from_disk_and_cache_in_memory(query, qcx, &key, &dep_node)
|
||||||
}) {
|
}) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -452,17 +455,24 @@ where
|
||||||
let diagnostics = Lock::new(ThinVec::new());
|
let diagnostics = Lock::new(ThinVec::new());
|
||||||
|
|
||||||
let (result, dep_node_index) =
|
let (result, dep_node_index) =
|
||||||
qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || {
|
qcx.start_query(job_id, query.depth_limit(), Some(&diagnostics), || {
|
||||||
if Q::ANON {
|
if query.anon() {
|
||||||
return dep_graph
|
return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind(), || {
|
||||||
.with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || Q::compute(qcx, key));
|
query.compute(qcx, key)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// `to_dep_node` is expensive for some `DepKind`s.
|
// `to_dep_node` is expensive for some `DepKind`s.
|
||||||
let dep_node =
|
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,
|
||||||
|
(key, query),
|
||||||
|
|qcx, (key, query)| query.compute(qcx, key),
|
||||||
|
query.hash_result(),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
||||||
|
@ -471,7 +481,7 @@ where
|
||||||
let side_effects = QuerySideEffects { diagnostics };
|
let side_effects = QuerySideEffects { diagnostics };
|
||||||
|
|
||||||
if std::intrinsics::unlikely(!side_effects.is_empty()) {
|
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);
|
qcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
|
||||||
} else {
|
} else {
|
||||||
qcx.store_side_effects(dep_node_index, side_effects);
|
qcx.store_side_effects(dep_node_index, side_effects);
|
||||||
|
@ -483,6 +493,7 @@ where
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
|
fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
|
||||||
|
query: Q,
|
||||||
qcx: Qcx,
|
qcx: Qcx,
|
||||||
key: &Q::Key,
|
key: &Q::Key,
|
||||||
dep_node: &DepNode<Qcx::DepKind>,
|
dep_node: &DepNode<Qcx::DepKind>,
|
||||||
|
@ -501,7 +512,7 @@ where
|
||||||
|
|
||||||
// First we try to load the result from the on-disk cache.
|
// First we try to load the result from the on-disk cache.
|
||||||
// Some things are never cached on disk.
|
// 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();
|
let prof_timer = qcx.dep_context().profiler().incr_cache_loading();
|
||||||
|
|
||||||
// The call to `with_query_deserialization` enforces that no new `DepNodes`
|
// The call to `with_query_deserialization` enforces that no new `DepNodes`
|
||||||
|
@ -535,7 +546,7 @@ where
|
||||||
if std::intrinsics::unlikely(
|
if std::intrinsics::unlikely(
|
||||||
try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich,
|
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));
|
return Some((result, dep_node_index));
|
||||||
|
@ -554,7 +565,7 @@ where
|
||||||
let prof_timer = qcx.dep_context().profiler().query_provider();
|
let prof_timer = qcx.dep_context().profiler().query_provider();
|
||||||
|
|
||||||
// The dep-graph for this computation is already in-place.
|
// 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());
|
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
||||||
|
|
||||||
|
@ -567,7 +578,7 @@ where
|
||||||
//
|
//
|
||||||
// See issue #82920 for an example of a miscompilation that would get turned into
|
// See issue #82920 for an example of a miscompilation that would get turned into
|
||||||
// an ICE by this check
|
// 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))
|
Some((result, dep_node_index))
|
||||||
}
|
}
|
||||||
|
@ -688,19 +699,23 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result:
|
||||||
///
|
///
|
||||||
/// Note: The optimization is only available during incr. comp.
|
/// Note: The optimization is only available during incr. comp.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn ensure_must_run<Q, Qcx>(qcx: Qcx, key: &Q::Key) -> (bool, Option<DepNode<Qcx::DepKind>>)
|
fn ensure_must_run<Q, Qcx>(
|
||||||
|
query: Q,
|
||||||
|
qcx: Qcx,
|
||||||
|
key: &Q::Key,
|
||||||
|
) -> (bool, Option<DepNode<Qcx::DepKind>>)
|
||||||
where
|
where
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
if Q::EVAL_ALWAYS {
|
if query.eval_always() {
|
||||||
return (true, None);
|
return (true, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensuring an anonymous query makes no sense
|
// 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();
|
let dep_graph = qcx.dep_context().dep_graph();
|
||||||
match dep_graph.try_mark_green(qcx, &dep_node) {
|
match dep_graph.try_mark_green(qcx, &dep_node) {
|
||||||
|
@ -728,15 +743,19 @@ pub enum QueryMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Value>
|
pub fn get_query<Q, Qcx>(
|
||||||
|
query: Q,
|
||||||
|
qcx: Qcx,
|
||||||
|
span: Span,
|
||||||
|
key: Q::Key,
|
||||||
|
mode: QueryMode,
|
||||||
|
) -> Option<Q::Value>
|
||||||
where
|
where
|
||||||
D: DepKind,
|
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Q::Value: Value<Qcx::DepContext, D>,
|
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
let dep_node = if let QueryMode::Ensure = mode {
|
let dep_node = if let QueryMode::Ensure = mode {
|
||||||
let (must_run, dep_node) = ensure_must_run::<Q, _>(qcx, &key);
|
let (must_run, dep_node) = ensure_must_run(query, qcx, &key);
|
||||||
if !must_run {
|
if !must_run {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -746,28 +765,30 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
let (result, dep_node_index) =
|
let (result, dep_node_index) =
|
||||||
ensure_sufficient_stack(|| try_execute_query::<Q, Qcx>(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 {
|
if let Some(dep_node_index) = dep_node_index {
|
||||||
qcx.dep_context().dep_graph().read_index(dep_node_index)
|
qcx.dep_context().dep_graph().read_index(dep_node_index)
|
||||||
}
|
}
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn force_query<Q, Qcx, D>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepKind>)
|
pub fn force_query<Q, Qcx>(
|
||||||
where
|
query: Q,
|
||||||
D: DepKind,
|
qcx: Qcx,
|
||||||
|
key: Q::Key,
|
||||||
|
dep_node: DepNode<<Qcx as HasDepContext>::DepKind>,
|
||||||
|
) where
|
||||||
Q: QueryConfig<Qcx>,
|
Q: QueryConfig<Qcx>,
|
||||||
Q::Value: Value<Qcx::DepContext, D>,
|
|
||||||
Qcx: QueryContext,
|
Qcx: QueryContext,
|
||||||
{
|
{
|
||||||
// We may be concurrently trying both execute and force a query.
|
// We may be concurrently trying both execute and force a query.
|
||||||
// Ensure that only one of them runs the 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());
|
qcx.dep_context().profiler().query_cache_hit(index.into());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(!Q::ANON);
|
debug_assert!(!query.anon());
|
||||||
|
|
||||||
ensure_sufficient_stack(|| try_execute_query::<Q, _>(qcx, DUMMY_SP, key, Some(dep_node)));
|
ensure_sufficient_stack(|| try_execute_query(query, qcx, DUMMY_SP, key, Some(dep_node)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue