diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index b628224db5369..d6310b62b2759 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -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> - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> + QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> where for<'a> C::Key: HashStable>, { + 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>; + type Dispatcher: QueryDispatcher>; const NAME: &'static &'static str; fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher; - fn restore_val( - value: >>::Value, - ) -> Self::UnerasedValue; + fn restore_val(value: ::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 6ead03a527a7a..0223981fd55dc 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>, + query: impl QueryDispatcher>, 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>, + Q: QueryDispatcher>, { 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>, + Q: QueryDispatcher>, { // 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 = - >>::Key::fingerprint_style(); + let fingerprint_style = ::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: >>::Value) -> Self::UnerasedValue { + fn restore_val(value: ::Value) -> Self::UnerasedValue { restore::>(value) } } diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index bba1703dfbb6b..1ca76a70364c9 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_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 = Option, &V) -> Fingerprint>; +/// Unambiguous shorthand for `::DepContext`. +#[expect(type_alias_bounds)] +type DepContextOf = + <::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 = Option, &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: 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 + Eq + Hash + Copy + Debug; + type Key: DepNodeParams> + Eq + Hash + Copy + Debug; type Value: Copy; type Cache: QueryCache; @@ -33,36 +41,40 @@ pub trait QueryDispatcher: 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 - where - Qcx: 'a; + fn query_state<'a>( + self, + tcx: Self::Qcx, + ) -> &'a QueryState::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, 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, 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; - 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, cycle_error: &CycleError, guar: ErrorGuaranteed, ) -> Self::Value; @@ -77,7 +89,7 @@ pub trait QueryDispatcher: Copy { fn hash_result(self) -> HashResult; // 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, 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 9afad1546e9eb..7e9f83e8fe82b 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -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(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value where - Q: QueryDispatcher, - 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( +fn handle_cycle_error( query: Q, - qcx: Qcx, + qcx: Q::Qcx, cycle_error: &CycleError, error: Diag<'_>, ) -> Q::Value where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { match query.cycle_error_handling() { CycleErrorHandling::Error => { @@ -272,15 +272,14 @@ where #[cold] #[inline(never)] -fn cycle_error( +fn cycle_error( query: Q, - qcx: Qcx, + qcx: Q::Qcx, try_execute: QueryJobId, span: Span, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - 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( +fn wait_for_query( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, - latch: QueryLatch, + latch: QueryLatch<::QueryInfo>, current: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - 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( +fn try_execute_query( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - 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::(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( +fn execute_job( query: Q, - qcx: Qcx, - state: &QueryState, + qcx: Q::Qcx, + state: &QueryState::QueryInfo>, key: Q::Key, key_hash: u64, id: QueryJobId, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - 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( +fn execute_job_non_incr( query: Q, - qcx: Qcx, + qcx: Q::Qcx, key: Q::Key, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, - 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( +fn execute_job_incr( query: Q, - qcx: Qcx, - dep_graph_data: &DepGraphData, + qcx: Q::Qcx, + dep_graph_data: &DepGraphData<::Deps>, key: Q::Key, mut dep_node_opt: Option, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, - 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( +fn try_load_from_disk_and_cache_in_memory( query: Q, - dep_graph_data: &DepGraphData, - qcx: Qcx, + dep_graph_data: &DepGraphData<::Deps>, + qcx: Q::Qcx, key: &Q::Key, dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where - Q: QueryDispatcher, - 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( /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run( +fn ensure_must_run( query: Q, - qcx: Qcx, + qcx: Q::Qcx, key: &Q::Key, check_cache: bool, ) -> (bool, Option) where - Q: QueryDispatcher, - 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(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value +pub fn get_query_non_incr(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); - ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) + ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) } #[inline(always)] -pub fn get_query_incr( +pub fn get_query_incr( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, mode: QueryMode, ) -> Option where - Q: QueryDispatcher, - 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::(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(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) +pub fn force_query(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) where - Q: QueryDispatcher, - 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::(query, qcx, DUMMY_SP, key, Some(dep_node)) }); }