Make QueryDispatcher::Qcx an associated type
This commit is contained in:
parent
de6d33c033
commit
2a96ea0bee
4 changed files with 86 additions and 92 deletions
|
|
@ -67,11 +67,11 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA
|
|||
|
||||
// This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`.
|
||||
impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool>
|
||||
QueryDispatcher<QueryCtxt<'tcx>>
|
||||
for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE>
|
||||
where
|
||||
for<'a> C::Key: HashStable<StableHashingContext<'a>>,
|
||||
{
|
||||
type Qcx = QueryCtxt<'tcx>;
|
||||
type Key = C::Key;
|
||||
type Value = C::Value;
|
||||
type Cache = C;
|
||||
|
|
@ -104,10 +104,7 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache
|
||||
where
|
||||
'tcx: 'a,
|
||||
{
|
||||
fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache {
|
||||
// Safety:
|
||||
// This is just manually doing the subfield referencing through pointer math.
|
||||
unsafe {
|
||||
|
|
@ -215,15 +212,13 @@ where
|
|||
/// on the type `rustc_query_impl::query_impl::$name::QueryType`.
|
||||
trait QueryDispatcherUnerased<'tcx> {
|
||||
type UnerasedValue;
|
||||
type Dispatcher: QueryDispatcher<QueryCtxt<'tcx>>;
|
||||
type Dispatcher: QueryDispatcher<Qcx = QueryCtxt<'tcx>>;
|
||||
|
||||
const NAME: &'static &'static str;
|
||||
|
||||
fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher;
|
||||
|
||||
fn restore_val(
|
||||
value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value,
|
||||
) -> Self::UnerasedValue;
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue;
|
||||
}
|
||||
|
||||
pub fn query_system<'a>(
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>(
|
|||
}
|
||||
|
||||
pub(crate) fn query_key_hash_verify<'tcx>(
|
||||
query: impl QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
query: impl QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
qcx: QueryCtxt<'tcx>,
|
||||
) {
|
||||
let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name());
|
||||
|
|
@ -442,7 +442,7 @@ pub(crate) fn query_key_hash_verify<'tcx>(
|
|||
|
||||
fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
debug_assert!(tcx.dep_graph.is_green(&dep_node));
|
||||
|
||||
|
|
@ -488,7 +488,7 @@ where
|
|||
|
||||
fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
|
||||
where
|
||||
Q: QueryDispatcher<QueryCtxt<'tcx>>,
|
||||
Q: QueryDispatcher<Qcx = QueryCtxt<'tcx>>,
|
||||
{
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
|
|
@ -523,8 +523,7 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
|
|||
where
|
||||
Q: QueryDispatcherUnerased<'tcx>,
|
||||
{
|
||||
let fingerprint_style =
|
||||
<Q::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Key::fingerprint_style();
|
||||
let fingerprint_style = <Q::Dispatcher as QueryDispatcher>::Key::fingerprint_style();
|
||||
|
||||
if is_anon || !fingerprint_style.reconstructible() {
|
||||
return DepKindVTable {
|
||||
|
|
@ -731,7 +730,7 @@ macro_rules! define_queries {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher<QueryCtxt<'tcx>>>::Value) -> Self::UnerasedValue {
|
||||
fn restore_val(value: <Self::Dispatcher as QueryDispatcher>::Value) -> Self::UnerasedValue {
|
||||
restore::<queries::$name::Value<'tcx>>(value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,18 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
|||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
use super::QueryStackFrameExtra;
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
|
||||
|
||||
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
|
||||
|
||||
/// Unambiguous shorthand for `<This::Qcx as HasDepContext>::DepContext`.
|
||||
#[expect(type_alias_bounds)]
|
||||
type DepContextOf<This: QueryDispatcher> =
|
||||
<<This as QueryDispatcher>::Qcx as HasDepContext>::DepContext;
|
||||
|
||||
/// Trait that can be used as a vtable for a single query, providing operations
|
||||
/// and metadata for that query.
|
||||
///
|
||||
|
|
@ -20,12 +25,15 @@ pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerp
|
|||
/// Those types are not visible from this `rustc_query_system` crate.
|
||||
///
|
||||
/// "Dispatcher" should be understood as a near-synonym of "vtable".
|
||||
pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
||||
pub trait QueryDispatcher: Copy {
|
||||
fn name(self) -> &'static str;
|
||||
|
||||
/// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`.
|
||||
type Qcx: QueryContext;
|
||||
|
||||
// `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
|
||||
// but it isn't necessary.
|
||||
type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Copy + Debug;
|
||||
type Key: DepNodeParams<DepContextOf<Self>> + Eq + Hash + Copy + Debug;
|
||||
type Value: Copy;
|
||||
|
||||
type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
|
||||
|
|
@ -33,36 +41,40 @@ pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
|||
fn format_value(self) -> fn(&Self::Value) -> String;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::QueryInfo>
|
||||
where
|
||||
Qcx: 'a;
|
||||
fn query_state<'a>(
|
||||
self,
|
||||
tcx: Self::Qcx,
|
||||
) -> &'a QueryState<Self::Key, <Self::Qcx as QueryContext>::QueryInfo>;
|
||||
|
||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||
fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache
|
||||
where
|
||||
Qcx: 'a;
|
||||
fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache;
|
||||
|
||||
fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool;
|
||||
fn cache_on_disk(self, tcx: DepContextOf<Self>, key: &Self::Key) -> bool;
|
||||
|
||||
// Don't use this method to compute query results, instead use the methods on TyCtxt
|
||||
fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value;
|
||||
fn execute_query(self, tcx: DepContextOf<Self>, k: Self::Key) -> Self::Value;
|
||||
|
||||
fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value;
|
||||
fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value;
|
||||
|
||||
fn try_load_from_disk(
|
||||
self,
|
||||
tcx: Qcx,
|
||||
tcx: Self::Qcx,
|
||||
key: &Self::Key,
|
||||
prev_index: SerializedDepNodeIndex,
|
||||
index: DepNodeIndex,
|
||||
) -> Option<Self::Value>;
|
||||
|
||||
fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
|
||||
fn loadable_from_disk(
|
||||
self,
|
||||
qcx: Self::Qcx,
|
||||
key: &Self::Key,
|
||||
idx: SerializedDepNodeIndex,
|
||||
) -> bool;
|
||||
|
||||
/// Synthesize an error value to let compilation continue after a cycle.
|
||||
fn value_from_cycle_error(
|
||||
self,
|
||||
tcx: Qcx::DepContext,
|
||||
tcx: DepContextOf<Self>,
|
||||
cycle_error: &CycleError<QueryStackFrameExtra>,
|
||||
guar: ErrorGuaranteed,
|
||||
) -> Self::Value;
|
||||
|
|
@ -77,7 +89,7 @@ pub trait QueryDispatcher<Qcx: QueryContext>: Copy {
|
|||
fn hash_result(self) -> HashResult<Self::Value>;
|
||||
|
||||
// Just here for convenience and checking that the key matches the kind, don't override this.
|
||||
fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode {
|
||||
fn construct_dep_node(self, tcx: DepContextOf<Self>, key: &Self::Key) -> DepNode {
|
||||
DepNode::construct(tcx, self.dep_kind(), key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ use rustc_span::{DUMMY_SP, Span};
|
|||
use tracing::instrument;
|
||||
|
||||
use super::{QueryDispatcher, QueryStackFrameExtra};
|
||||
use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
|
||||
use crate::dep_graph::{
|
||||
DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext,
|
||||
};
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::query::caches::QueryCache;
|
||||
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
|
||||
|
|
@ -124,24 +126,22 @@ where
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn mk_cycle<Q, Qcx>(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value
|
||||
fn mk_cycle<Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
|
||||
handle_cycle_error(query, qcx, &cycle_error, error)
|
||||
}
|
||||
|
||||
fn handle_cycle_error<Q, Qcx>(
|
||||
fn handle_cycle_error<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
cycle_error: &CycleError,
|
||||
error: Diag<'_>,
|
||||
) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
match query.cycle_error_handling() {
|
||||
CycleErrorHandling::Error => {
|
||||
|
|
@ -272,15 +272,14 @@ where
|
|||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn cycle_error<Q, Qcx>(
|
||||
fn cycle_error<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
try_execute: QueryJobId,
|
||||
span: Span,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Ensure there was no errors collecting all active jobs.
|
||||
// We need the complete map to ensure we find a cycle to break.
|
||||
|
|
@ -291,17 +290,16 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn wait_for_query<Q, Qcx>(
|
||||
fn wait_for_query<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
latch: QueryLatch<Qcx::QueryInfo>,
|
||||
latch: QueryLatch<<Q::Qcx as QueryContext>::QueryInfo>,
|
||||
current: Option<QueryJobId>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// For parallel queries, we'll block and wait until the query running
|
||||
// in another thread has completed. Record how long we wait in the
|
||||
|
|
@ -341,16 +339,15 @@ where
|
|||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn try_execute_query<Q, Qcx, const INCR: bool>(
|
||||
fn try_execute_query<Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
let state = query.query_state(qcx);
|
||||
let key_hash = sharded::make_hash(&key);
|
||||
|
|
@ -382,7 +379,7 @@ where
|
|||
// Drop the lock before we start executing the query
|
||||
drop(state_lock);
|
||||
|
||||
execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node)
|
||||
execute_job::<Q, INCR>(query, qcx, state, key, key_hash, id, dep_node)
|
||||
}
|
||||
Entry::Occupied(mut entry) => {
|
||||
match &mut entry.get_mut().1 {
|
||||
|
|
@ -411,18 +408,17 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job<Q, Qcx, const INCR: bool>(
|
||||
fn execute_job<Q, const INCR: bool>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
state: &QueryState<Q::Key, Qcx::QueryInfo>,
|
||||
qcx: Q::Qcx,
|
||||
state: &QueryState<Q::Key, <Q::Qcx as QueryContext>::QueryInfo>,
|
||||
key: Q::Key,
|
||||
key_hash: u64,
|
||||
id: QueryJobId,
|
||||
dep_node: Option<DepNode>,
|
||||
) -> (Q::Value, Option<DepNodeIndex>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Use `JobOwner` so the query will be poisoned if executing it panics.
|
||||
let job_owner = JobOwner { state, key };
|
||||
|
|
@ -484,15 +480,14 @@ where
|
|||
|
||||
// Fast path for when incr. comp. is off.
|
||||
#[inline(always)]
|
||||
fn execute_job_non_incr<Q, Qcx>(
|
||||
fn execute_job_non_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
key: Q::Key,
|
||||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -521,17 +516,16 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn execute_job_incr<Q, Qcx>(
|
||||
fn execute_job_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
dep_graph_data: &DepGraphData<Qcx::Deps>,
|
||||
qcx: Q::Qcx,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
key: Q::Key,
|
||||
mut dep_node_opt: Option<DepNode>,
|
||||
job_id: QueryJobId,
|
||||
) -> (Q::Value, DepNodeIndex)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
if !query.anon() && !query.eval_always() {
|
||||
// `to_dep_node` is expensive for some `DepKind`s.
|
||||
|
|
@ -577,16 +571,15 @@ where
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
|
||||
fn try_load_from_disk_and_cache_in_memory<Q>(
|
||||
query: Q,
|
||||
dep_graph_data: &DepGraphData<Qcx::Deps>,
|
||||
qcx: Qcx,
|
||||
dep_graph_data: &DepGraphData<<Q::Qcx as HasDepContext>::Deps>,
|
||||
qcx: Q::Qcx,
|
||||
key: &Q::Key,
|
||||
dep_node: &DepNode,
|
||||
) -> Option<(Q::Value, DepNodeIndex)>
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// Note this function can be called concurrently from the same query
|
||||
// We must ensure that this is handled correctly.
|
||||
|
|
@ -764,15 +757,14 @@ fn incremental_verify_ich_failed<Tcx>(
|
|||
///
|
||||
/// Note: The optimization is only available during incr. comp.
|
||||
#[inline(never)]
|
||||
fn ensure_must_run<Q, Qcx>(
|
||||
fn ensure_must_run<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
key: &Q::Key,
|
||||
check_cache: bool,
|
||||
) -> (bool, Option<DepNode>)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
if query.eval_always() {
|
||||
return (true, None);
|
||||
|
|
@ -817,27 +809,25 @@ pub enum QueryMode {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_non_incr<Q, Qcx>(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
pub fn get_query_non_incr<Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, Qcx, false>(query, qcx, span, key, None).0)
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, false>(query, qcx, span, key, None).0)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_query_incr<Q, Qcx>(
|
||||
pub fn get_query_incr<Q>(
|
||||
query: Q,
|
||||
qcx: Qcx,
|
||||
qcx: Q::Qcx,
|
||||
span: Span,
|
||||
key: Q::Key,
|
||||
mode: QueryMode,
|
||||
) -> Option<Q::Value>
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled());
|
||||
|
||||
|
|
@ -851,19 +841,17 @@ where
|
|||
None
|
||||
};
|
||||
|
||||
let (result, dep_node_index) = ensure_sufficient_stack(|| {
|
||||
try_execute_query::<_, _, true>(query, qcx, span, key, dep_node)
|
||||
});
|
||||
let (result, dep_node_index) =
|
||||
ensure_sufficient_stack(|| try_execute_query::<Q, true>(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<Q, Qcx>(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode)
|
||||
pub fn force_query<Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode)
|
||||
where
|
||||
Q: QueryDispatcher<Qcx>,
|
||||
Qcx: QueryContext,
|
||||
Q: QueryDispatcher,
|
||||
{
|
||||
// We may be concurrently trying both execute and force a query.
|
||||
// Ensure that only one of them runs the query.
|
||||
|
|
@ -875,6 +863,6 @@ where
|
|||
debug_assert!(!query.anon());
|
||||
|
||||
ensure_sufficient_stack(|| {
|
||||
try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
|
||||
try_execute_query::<Q, true>(query, qcx, DUMMY_SP, key, Some(dep_node))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue