diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ad63251363e25..cea50f95df4b4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -88,7 +88,7 @@ use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState}; +use rustc_query_system::query::{QueryMode, QueryState}; use rustc_session::Limits; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{ diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 7b85dac41aeff..2bda014a19fe7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -440,7 +440,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>, + pub $name: QueryState<'tcx, $($K)*>, )* } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 382b8750a1ce7..8fa4fb3090dbd 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -21,7 +21,7 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, - QueryStackDeferred, QueryState, get_query_incr, get_query_non_incr, + QueryState, get_query_incr, get_query_non_incr, }; use rustc_span::{ErrorGuaranteed, Span}; @@ -66,7 +66,7 @@ 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<'tcx> for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> where for<'a> C::Key: HashStable>, { @@ -86,10 +86,7 @@ where } #[inline(always)] - fn query_state<'a>( - self, - qcx: QueryCtxt<'tcx>, - ) -> &'a QueryState> + fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Key> where QueryCtxt<'tcx>: 'a, { @@ -98,7 +95,7 @@ where unsafe { &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) .byte_add(self.vtable.query_state) - .cast::>>() + .cast::>() } } @@ -211,13 +208,15 @@ where /// on the type `rustc_query_impl::query_impl::$name::QueryType`. trait QueryDispatcherUnerased<'tcx> { type UnerasedValue; - type Dispatcher: QueryDispatcher>; + type Dispatcher: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>; 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 c71352c3fd202..ef7a62351930d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -60,9 +60,7 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> { } } -impl<'tcx> QueryContext for QueryCtxt<'tcx> { - type QueryInfo = QueryStackDeferred<'tcx>; - +impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { #[inline] fn jobserver_proxy(&self) -> &Proxy { &self.tcx.jobserver_proxy @@ -93,10 +91,7 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> { /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, /// especially when called from within a deadlock handler, unless a /// complete map is needed and no deadlock is possible at this call site. - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result>, QueryMap>> { + fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>> { let mut jobs = QueryMap::default(); let mut complete = true; @@ -322,7 +317,7 @@ macro_rules! should_ever_cache_on_disk { }; } -fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( +fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( (tcx, key, kind, name, do_describe): ( TyCtxt<'tcx>, K, @@ -373,18 +368,16 @@ pub(crate) fn create_query_frame< ) -> QueryStackFrame> { let def_id = key.key_as_def_id(); - let hash = || { - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - kind.as_usize().hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() - }) - }; + let hash = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + kind.as_usize().hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::() + }); let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); let info = - QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra); + QueryStackDeferred::new((tcx, key, kind, name, do_describe), mk_query_stack_frame_extra); QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } @@ -417,7 +410,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( } pub(crate) fn query_key_hash_verify<'tcx>( - query: impl QueryDispatcher>, + query: impl QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, qcx: QueryCtxt<'tcx>, ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); @@ -445,7 +438,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<'tcx, Qcx = QueryCtxt<'tcx>>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); @@ -491,7 +484,7 @@ where fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where - Q: QueryDispatcher>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: @@ -734,14 +727,14 @@ macro_rules! define_queries { } #[inline(always)] - fn restore_val(value: ::Value) -> Self::UnerasedValue { + fn restore_val(value: >::Value) -> Self::UnerasedValue { erase::restore_val::>(value) } } pub(crate) fn collect_active_jobs<'tcx>( tcx: TyCtxt<'tcx>, - qmap: &mut QueryMap>, + qmap: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { let make_query = |tcx, key| { @@ -825,7 +818,7 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. const COLLECT_ACTIVE_JOBS: &[ - for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap>, bool) -> Option<()> + for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, bool) -> Option<()> ] = &[$(query_impl::$name::collect_active_jobs),*]; diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index f0cc9636b75c2..6d46d144d0f18 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -519,7 +519,11 @@ impl DepGraph { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { + pub fn record_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) { if let Some(ref data) = self.data { D::read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, @@ -532,7 +536,7 @@ impl DepGraph { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - pub fn force_diagnostic_node( + pub fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -669,7 +673,7 @@ impl DepGraphData { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - fn encode_diagnostic( + fn encode_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, diagnostic: &DiagInner, @@ -693,7 +697,7 @@ impl DepGraphData { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - fn force_diagnostic_node( + fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -843,7 +847,7 @@ impl DepGraph { DepNodeColor::Unknown } - pub fn try_mark_green>( + pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -858,7 +862,7 @@ impl DepGraphData { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub(crate) fn try_mark_green>( + pub(crate) fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -883,7 +887,7 @@ impl DepGraphData { } #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, @@ -973,7 +977,7 @@ impl DepGraphData { /// Try to mark a dep-node which existed in the previous compilation session as green. #[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")] - fn try_mark_previous_green>( + fn try_mark_previous_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index 1ca76a70364c9..d7dd6dd6464a5 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -14,8 +14,8 @@ pub type HashResult = Option, &V) -> Fingerp /// Unambiguous shorthand for `::DepContext`. #[expect(type_alias_bounds)] -type DepContextOf = - <::Qcx as HasDepContext>::DepContext; +type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> = + <>::Qcx as HasDepContext>::DepContext; /// Trait that can be used as a vtable for a single query, providing operations /// and metadata for that query. @@ -25,15 +25,15 @@ type DepContextOf = /// 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<'tcx>: Copy { fn name(self) -> &'static str; /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`. - type Qcx: QueryContext; + type Qcx: QueryContext<'tcx>; // `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; @@ -41,18 +41,15 @@ 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: Self::Qcx, - ) -> &'a QueryState::QueryInfo>; + fn query_state<'a>(self, tcx: Self::Qcx) -> &'a QueryState<'tcx, Self::Key>; // Don't use this method to access query results, instead use the methods on TyCtxt fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache; - fn cache_on_disk(self, tcx: DepContextOf, key: &Self::Key) -> bool; + fn cache_on_disk(self, tcx: DepContextOf<'tcx, 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: DepContextOf, k: Self::Key) -> Self::Value; + fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value; fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value; @@ -74,7 +71,7 @@ pub trait QueryDispatcher: Copy { /// Synthesize an error value to let compilation continue after a cycle. fn value_from_cycle_error( self, - tcx: DepContextOf, + tcx: DepContextOf<'tcx, Self>, cycle_error: &CycleError, guar: ErrorGuaranteed, ) -> Self::Value; @@ -89,7 +86,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: DepContextOf, key: &Self::Key) -> DepNode { + fn construct_dep_node(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 5810ce0cbe668..177bcd63cbc62 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -12,7 +12,7 @@ use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; -use super::QueryStackFrameExtra; +use super::{QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; @@ -26,8 +26,8 @@ pub struct QueryInfo { pub query: QueryStackFrame, } -impl QueryInfo { - pub(crate) fn lift>( +impl<'tcx> QueryInfo> { + pub(crate) fn lift>( &self, qcx: Qcx, ) -> QueryInfo { @@ -35,39 +35,39 @@ impl QueryInfo { } } -pub type QueryMap = FxHashMap>; +pub type QueryMap<'tcx> = FxHashMap>; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct QueryJobId(pub NonZero); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame> { map.get(&self).unwrap().query.clone() } - fn span(self, map: &QueryMap) -> Span { + fn span<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Span { map.get(&self).unwrap().job.span } - fn parent(self, map: &QueryMap) -> Option { + fn parent<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option { map.get(&self).unwrap().job.parent } - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { + fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<'tcx>> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone, Debug)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo<'tcx> { + pub query: QueryStackFrame>, + pub job: QueryJob<'tcx>, } /// Represents an active query job. #[derive(Debug)] -pub struct QueryJob { +pub struct QueryJob<'tcx> { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -77,23 +77,23 @@ pub struct QueryJob { pub parent: Option, /// The latch that is used to wait on this job. - latch: Option>, + latch: Option>, } -impl Clone for QueryJob { +impl<'tcx> Clone for QueryJob<'tcx> { fn clone(&self) -> Self { Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } } } -impl QueryJob { +impl<'tcx> QueryJob<'tcx> { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { QueryJob { id, span, parent, latch: None } } - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -113,12 +113,12 @@ impl QueryJob { } impl QueryJobId { - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack<'tcx>( &self, - query_map: QueryMap, + query_map: QueryMap<'tcx>, current_job: &Option, span: Span, - ) -> CycleError { + ) -> CycleError> { // Find the waitee amongst `current_job` parents let mut cycle = Vec::new(); let mut current_job = Option::clone(current_job); @@ -152,7 +152,10 @@ impl QueryJobId { #[cold] #[inline(never)] - pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { + pub fn find_dep_kind_root<'tcx>( + &self, + query_map: QueryMap<'tcx>, + ) -> (QueryJobInfo<'tcx>, usize) { let mut depth = 1; let info = query_map.get(&self).unwrap(); let dep_kind = info.query.dep_kind; @@ -172,31 +175,31 @@ impl QueryJobId { } #[derive(Debug)] -struct QueryWaiter { +struct QueryWaiter<'tcx> { query: Option, condvar: Condvar, span: Span, - cycle: Mutex>>, + cycle: Mutex>>>, } #[derive(Debug)] -struct QueryLatchInfo { +struct QueryLatchInfo<'tcx> { complete: bool, - waiters: Vec>>, + waiters: Vec>>, } #[derive(Debug)] -pub(super) struct QueryLatch { - info: Arc>>, +pub(super) struct QueryLatch<'tcx> { + info: Arc>>, } -impl Clone for QueryLatch { +impl<'tcx> Clone for QueryLatch<'tcx> { fn clone(&self) -> Self { Self { info: Arc::clone(&self.info) } } } -impl QueryLatch { +impl<'tcx> QueryLatch<'tcx> { fn new() -> Self { QueryLatch { info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -206,10 +209,10 @@ impl QueryLatch { /// Awaits for the query job to complete. pub(super) fn wait_on( &self, - qcx: impl QueryContext, + qcx: impl QueryContext<'tcx>, query: Option, span: Span, - ) -> Result<(), CycleError> { + ) -> Result<(), CycleError>> { let waiter = Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); self.wait_on_inner(qcx, &waiter); @@ -224,7 +227,7 @@ impl QueryLatch { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, qcx: impl QueryContext, waiter: &Arc>) { + fn wait_on_inner(&self, qcx: impl QueryContext<'tcx>, waiter: &Arc>) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -260,7 +263,7 @@ impl QueryLatch { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc> { + fn extract_waiter(&self, waiter: usize) -> Arc> { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -280,8 +283,8 @@ type Waiter = (QueryJobId, usize); /// For visits of resumable waiters it returns Some(Some(Waiter)) which has the /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. -fn visit_waiters( - query_map: &QueryMap, +fn visit_waiters<'tcx, F>( + query_map: &QueryMap<'tcx>, query: QueryJobId, mut visit: F, ) -> Option> @@ -314,8 +317,8 @@ where /// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. -fn cycle_check( - query_map: &QueryMap, +fn cycle_check<'tcx>( + query_map: &QueryMap<'tcx>, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -354,8 +357,8 @@ fn cycle_check( /// Finds out if there's a path to the compiler root (aka. code which isn't in a query) /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root<'tcx>( + query_map: &QueryMap<'tcx>, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -376,7 +379,7 @@ fn connected_to_root( } // Deterministically pick an query from a list -fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, 'tcx, T, F>(query_map: &QueryMap<'tcx>, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), { @@ -401,10 +404,10 @@ where /// the function return true. /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle<'tcx>( + query_map: &QueryMap<'tcx>, jobs: &mut Vec, - wakelist: &mut Vec>>, + wakelist: &mut Vec>>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -505,10 +508,7 @@ fn remove_cycle( /// uses a query latch and then resuming that waiter. /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. -pub fn break_query_cycles( - query_map: QueryMap, - registry: &rustc_thread_pool::Registry, -) { +pub fn break_query_cycles<'tcx>(query_map: QueryMap<'tcx>, registry: &rustc_thread_pool::Registry) { let mut wakelist = Vec::new(); // It is OK per the comments: // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 @@ -602,7 +602,7 @@ pub fn report_cycle<'a>( sess.dcx().create_err(cycle_diag) } -pub fn print_query_stack( +pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( qcx: Qcx, mut current_query: Option, dcx: DiagCtxtHandle<'_>, diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 701253d50fcca..63202429679d2 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -58,22 +58,19 @@ pub struct QueryStackFrame { pub def_id_for_ty_in_cycle: Option, } -impl QueryStackFrame { +impl<'tcx> QueryStackFrame> { #[inline] pub fn new( - info: I, + info: QueryStackDeferred<'tcx>, dep_kind: DepKind, - hash: impl FnOnce() -> Hash64, + hash: Hash64, def_id: Option, def_id_for_ty_in_cycle: Option, ) -> Self { - Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle } + Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } } - fn lift>( - &self, - qcx: Qcx, - ) -> QueryStackFrame { + fn lift>(&self, qcx: Qcx) -> QueryStackFrame { QueryStackFrame { info: qcx.lift_query_info(&self.info), dep_kind: self.dep_kind, @@ -159,9 +156,7 @@ pub enum QuerySideEffect { Diagnostic(DiagInner), } -pub trait QueryContext: HasDepContext { - type QueryInfo: Clone; - +pub trait QueryContext<'tcx>: HasDepContext { /// Gets a jobserver reference which is used to release then acquire /// a token while waiting on a query. fn jobserver_proxy(&self) -> &Proxy; @@ -171,12 +166,9 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result, QueryMap>; + fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>>; - fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra; + fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra; /// Load a side effect associated to the node in the previous session. fn load_side_effect( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 7e9f83e8fe82b..c4431ff870d0c 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -18,7 +18,7 @@ use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; use tracing::instrument; -use super::{QueryDispatcher, QueryStackFrameExtra}; +use super::{QueryDispatcher, QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::{ DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext, }; @@ -34,23 +34,23 @@ fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } -pub struct QueryState { - active: Sharded)>>, +pub struct QueryState<'tcx, K> { + active: Sharded)>>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob<'tcx>), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryResult { +impl<'tcx> QueryResult<'tcx> { /// Unwraps the query job expecting that it has started. - fn expect_job(self) -> QueryJob { + fn expect_job(self) -> QueryJob<'tcx> { match self { Self::Started(job) => job, Self::Poisoned => { @@ -60,7 +60,7 @@ impl QueryResult { } } -impl QueryState +impl<'tcx, K> QueryState<'tcx, K> where K: Eq + Hash + Copy + Debug, { @@ -71,13 +71,13 @@ where pub fn collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame>, + jobs: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { let mut active = Vec::new(); - let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult)>>| { + let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<'tcx>)>>| { for (k, v) in iter.iter() { if let QueryResult::Started(ref job) = *v { active.push((*k, job.clone())); @@ -108,40 +108,40 @@ where } } -impl Default for QueryState { - fn default() -> QueryState { +impl<'tcx, K> Default for QueryState<'tcx, K> { + fn default() -> QueryState<'tcx, K> { QueryState { active: Default::default() } } } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K, I> +struct JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'a QueryState<'tcx, K>, key: K, } #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle<'tcx, Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { 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<'tcx, Q>( query: Q, qcx: Q::Qcx, cycle_error: &CycleError, error: Diag<'_>, ) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { match query.cycle_error_handling() { CycleErrorHandling::Error => { @@ -170,7 +170,7 @@ where } } -impl<'tcx, K, I> JobOwner<'tcx, K, I> +impl<'a, 'tcx, K> JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { @@ -207,7 +207,7 @@ where } } -impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I> +impl<'a, 'tcx, K> Drop for JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { @@ -241,8 +241,8 @@ pub struct CycleError { pub cycle: Vec>, } -impl CycleError { - fn lift>(&self, qcx: Qcx) -> CycleError { +impl<'tcx> CycleError> { + fn lift>(&self, qcx: Qcx) -> CycleError { CycleError { usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), @@ -272,14 +272,14 @@ where #[cold] #[inline(never)] -fn cycle_error( +fn cycle_error<'tcx, Q>( query: Q, qcx: Q::Qcx, try_execute: QueryJobId, span: Span, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. @@ -290,16 +290,16 @@ where } #[inline(always)] -fn wait_for_query( +fn wait_for_query<'tcx, Q>( query: Q, qcx: Q::Qcx, span: Span, key: Q::Key, - latch: QueryLatch<::QueryInfo>, + latch: QueryLatch<'tcx>, current: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the @@ -339,7 +339,7 @@ where } #[inline(never)] -fn try_execute_query( +fn try_execute_query<'tcx, Q, const INCR: bool>( query: Q, qcx: Q::Qcx, span: Span, @@ -347,7 +347,7 @@ fn try_execute_query( dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); @@ -408,17 +408,17 @@ where } #[inline(always)] -fn execute_job( +fn execute_job<'tcx, Q, const INCR: bool>( query: Q, qcx: Q::Qcx, - state: &QueryState::QueryInfo>, + state: &QueryState<'tcx, Q::Key>, key: Q::Key, key_hash: u64, id: QueryJobId, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Use `JobOwner` so the query will be poisoned if executing it panics. let job_owner = JobOwner { state, key }; @@ -480,14 +480,14 @@ where // Fast path for when incr. comp. is off. #[inline(always)] -fn execute_job_non_incr( +fn execute_job_non_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, key: Q::Key, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); @@ -516,7 +516,7 @@ where } #[inline(always)] -fn execute_job_incr( +fn execute_job_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, dep_graph_data: &DepGraphData<::Deps>, @@ -525,7 +525,7 @@ fn execute_job_incr( job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. @@ -571,7 +571,7 @@ where } #[inline(always)] -fn try_load_from_disk_and_cache_in_memory( +fn try_load_from_disk_and_cache_in_memory<'tcx, Q>( query: Q, dep_graph_data: &DepGraphData<::Deps>, qcx: Q::Qcx, @@ -579,7 +579,7 @@ fn try_load_from_disk_and_cache_in_memory( dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -757,14 +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<'tcx, Q>( query: Q, qcx: Q::Qcx, key: &Q::Key, check_cache: bool, ) -> (bool, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { if query.eval_always() { return (true, None); @@ -809,9 +809,9 @@ pub enum QueryMode { } #[inline(always)] -pub fn get_query_non_incr(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value +pub fn get_query_non_incr<'tcx, Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); @@ -819,7 +819,7 @@ where } #[inline(always)] -pub fn get_query_incr( +pub fn get_query_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, span: Span, @@ -827,7 +827,7 @@ pub fn get_query_incr( mode: QueryMode, ) -> Option where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled()); @@ -849,9 +849,9 @@ where Some(result) } -pub fn force_query(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) +pub fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query.