Make `QueryDispatcher::Qcx` an associated type
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index b628224..d6310b6 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs
@@ -67,11 +67,11 @@ fn clone(&self) -> Self { // 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 @@ fn query_state<'a>( } #[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 @@ fn hash_result(self) -> HashResult<Self::Value> { /// 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>(
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6ead03a..0223981 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -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 @@ pub(crate) fn try_load_from_disk<'tcx, V>( 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 @@ fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher { } #[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) } }
diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index bba1703..1ca76a7 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs
@@ -5,13 +5,18 @@ 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 @@ /// 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 @@ fn value_from_cycle_error( 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) } }
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 9afad15..7e9f83e 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -19,7 +19,9 @@ 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 @@ struct JobOwner<'tcx, K, I> #[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 @@ pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Va #[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 @@ fn cycle_error<Q, Qcx>( } #[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 @@ fn wait_for_query<Q, Qcx>( } #[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 @@ fn try_execute_query<Q, Qcx, const INCR: bool>( // 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 @@ fn try_execute_query<Q, Qcx, const INCR: bool>( } #[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 @@ fn execute_job<Q, Qcx, const INCR: bool>( // 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 @@ fn execute_job_non_incr<Q, Qcx>( } #[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 @@ fn execute_job_incr<Q, Qcx>( } #[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 @@ pub fn get_query_incr<Q, Qcx>( 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 @@ pub fn force_query<Q, Qcx>(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) 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)) }); }