From f8b30084ac5ae2845175a89fa66f174d6eb871b2 Mon Sep 17 00:00:00 2001 From: gimbles Date: Fri, 23 Dec 2022 18:39:49 +0530 Subject: [PATCH] Use DepKind instead of &str --- compiler/rustc_middle/src/values.rs | 23 ++-- compiler/rustc_query_impl/src/plumbing.rs | 24 ++-- .../rustc_query_system/src/query/config.rs | 2 +- compiler/rustc_query_system/src/query/job.rs | 104 ++++++++++-------- compiler/rustc_query_system/src/query/mod.rs | 13 ++- .../rustc_query_system/src/query/plumbing.rs | 79 ++++++------- compiler/rustc_query_system/src/values.rs | 10 +- 7 files changed, 141 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 70b98e59a8b..c242be57031 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -1,3 +1,4 @@ +use crate::dep_graph::DepKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan}; use rustc_hir as hir; @@ -11,16 +12,16 @@ use std::fmt::Write; -impl<'tcx> Value> for Ty<'_> { - fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { +impl<'tcx> Value, DepKind> for Ty<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { std::mem::transmute::, Ty<'_>>(tcx.ty_error()) } } } -impl<'tcx> Value> for ty::SymbolName<'_> { - fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { +impl<'tcx> Value, DepKind> for ty::SymbolName<'_> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. unsafe { @@ -31,12 +32,12 @@ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self { } } -impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { - fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self { +impl<'tcx> Value, DepKind> for ty::Binder<'_, ty::FnSig<'_>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self { let err = tcx.ty_error(); let arity = if let Some(frame) = stack.get(0) - && frame.query.name == "fn_sig" + && frame.query.dep_kind == DepKind::fn_sig && let Some(def_id) = frame.query.def_id && let Some(node) = tcx.hir().get_if_local(def_id) && let Some(sig) = node.fn_sig() @@ -61,12 +62,12 @@ fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self { } } -impl<'tcx> Value> for Representability { - fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self { +impl<'tcx> Value, DepKind> for Representability { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in cycle { - if info.query.name == "representability" + if info.query.dep_kind == DepKind::representability && let Some(field_id) = info.query.def_id && let Some(field_id) = field_id.as_local() && let Some(DefKind::Field) = info.query.def_kind @@ -80,7 +81,7 @@ fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self { } } for info in cycle { - if info.query.name == "representability_adt_ty" + if info.query.dep_kind == DepKind::representability_adt_ty && let Some(def_id) = info.query.ty_adt_id && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 8d5d84c5db4..9ffcc5672cc 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -66,7 +66,7 @@ fn current_query_job(&self) -> Option { tls::with_related_context(**self, |icx| icx.query) } - fn try_collect_active_jobs(&self) -> Option { + fn try_collect_active_jobs(&self) -> Option> { self.queries.try_collect_active_jobs(**self) } @@ -195,7 +195,7 @@ pub fn try_print_query_stack( #[derive(Clone, Copy)] pub(crate) struct QueryStruct<'tcx> { - pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>, + pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>, pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache), pub encode_query_results: Option, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>, @@ -313,7 +313,7 @@ pub(crate) fn create_query_frame< key: K, kind: DepKind, name: &'static str, -) -> QueryStackFrame { +) -> QueryStackFrame { // Disable visible paths printing for performance reasons. // Showing visible path instead of any path is not that important in production. let description = ty::print::with_no_visible_paths!( @@ -346,7 +346,7 @@ pub(crate) fn create_query_frame< }; let ty_adt_id = key.ty_adt_id(); - QueryStackFrame::new(name, description, span, def_id, def_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) @@ -378,7 +378,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where Q: QueryConfig>, Q::Key: DepNodeParams>, - Q::Value: Value>, + Q::Value: Value, DepKind>, { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: @@ -402,7 +402,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); let tcx = QueryCtxt::from_tcx(tcx); - force_query::(tcx, key, dep_node); + force_query::(tcx, key, dep_node); true } else { false @@ -480,7 +480,7 @@ fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { type Cache = query_storage::$name<'tcx>; #[inline(always)] - fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState + fn query_state<'a>(tcx: QueryCtxt<'tcx>) -> &'a QueryState where QueryCtxt<'tcx>: 'a { &tcx.queries.$name @@ -587,9 +587,10 @@ mod query_structs { use $crate::plumbing::{QueryStruct, QueryCtxt}; use $crate::profiling_support::QueryKeyStringCache; use rustc_query_system::query::QueryMap; + use rustc_middle::dep_graph::DepKind; pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> { - fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> { + fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> { None } fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {} @@ -675,7 +676,8 @@ pub struct Queries<'tcx> { $( $(#[$attr])* $name: QueryState< - as QueryConfig>>::Key + as QueryConfig>>::Key, + rustc_middle::dep_graph::DepKind, >, )* } @@ -684,7 +686,7 @@ impl<'tcx> Queries<'tcx> { pub(crate) fn try_collect_active_jobs( &'tcx self, tcx: TyCtxt<'tcx>, - ) -> Option { + ) -> Option> { let tcx = QueryCtxt { tcx, queries: self }; let mut jobs = QueryMap::default(); @@ -718,7 +720,7 @@ fn $name( mode: QueryMode, ) -> Option> { let qcx = QueryCtxt { tcx, queries: self }; - get_query::, _>(qcx, span, key, mode) + get_query::, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode) })* } }; diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 7d1b62ab102..24c960765df 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -21,7 +21,7 @@ pub trait QueryConfig { type Cache: QueryCache; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(tcx: Qcx) -> &'a QueryState + fn query_state<'a>(tcx: Qcx) -> &'a QueryState where Qcx: 'a; diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 49bbcf57804..d92e55413e5 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,6 +1,8 @@ +use crate::dep_graph::DepKind; use crate::error::CycleStack; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryStackFrame}; +use core::marker::PhantomData; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ @@ -28,48 +30,48 @@ /// Represents a span and a query key. #[derive(Clone, Debug)] -pub struct QueryInfo { +pub struct QueryInfo { /// The span corresponding to the reason for which this query was required. pub span: Span, - pub query: QueryStackFrame, + pub query: QueryStackFrame, } -pub type QueryMap = FxHashMap; +pub type QueryMap = FxHashMap>; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryJobId(pub NonZeroU64); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query(self, map: &QueryMap) -> QueryStackFrame { map.get(&self).unwrap().query.clone() } #[cfg(parallel_compiler)] - fn span(self, map: &QueryMap) -> Span { + fn span(self, map: &QueryMap) -> Span { map.get(&self).unwrap().job.span } #[cfg(parallel_compiler)] - fn parent(self, map: &QueryMap) -> Option { + fn parent(self, map: &QueryMap) -> Option { map.get(&self).unwrap().job.parent } #[cfg(parallel_compiler)] - fn latch<'a>(self, map: &'a QueryMap) -> Option<&'a QueryLatch> { + fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo { + pub query: QueryStackFrame, + pub job: QueryJob, } /// Represents an active query job. #[derive(Clone)] -pub struct QueryJob { +pub struct QueryJob { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -80,10 +82,11 @@ pub struct QueryJob { /// The latch that is used to wait on this job. #[cfg(parallel_compiler)] - latch: Option, + latch: Option>, + spooky: core::marker::PhantomData, } -impl QueryJob { +impl QueryJob { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { @@ -93,11 +96,12 @@ pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { parent, #[cfg(parallel_compiler)] latch: None, + spooky: PhantomData, } } #[cfg(parallel_compiler)] - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -123,12 +127,12 @@ impl QueryJobId { #[cold] #[inline(never)] #[cfg(not(parallel_compiler))] - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack( &self, - query_map: QueryMap, + query_map: QueryMap, 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); @@ -162,14 +166,18 @@ pub(super) fn find_cycle_in_stack( #[cold] #[inline(never)] - pub fn try_find_layout_root(&self, query_map: QueryMap) -> Option<(QueryJobInfo, usize)> { + pub fn try_find_layout_root( + &self, + query_map: QueryMap, + ) -> Option<(QueryJobInfo, usize)> { let mut last_layout = None; let mut current_id = Some(*self); let mut depth = 0; while let Some(id) = current_id { let info = query_map.get(&id).unwrap(); - if info.query.name == "layout_of" { + // FIXME: This string comparison should probably not be done. + if format!("{:?}", info.query.dep_kind) == "layout_of" { depth += 1; last_layout = Some((info.clone(), depth)); } @@ -180,15 +188,15 @@ pub fn try_find_layout_root(&self, query_map: QueryMap) -> Option<(QueryJobInfo, } #[cfg(parallel_compiler)] -struct QueryWaiter { +struct QueryWaiter { query: Option, condvar: Condvar, span: Span, - cycle: Lock>, + cycle: Lock>>, } #[cfg(parallel_compiler)] -impl QueryWaiter { +impl QueryWaiter { fn notify(&self, registry: &rayon_core::Registry) { rayon_core::mark_unblocked(registry); self.condvar.notify_one(); @@ -196,19 +204,19 @@ fn notify(&self, registry: &rayon_core::Registry) { } #[cfg(parallel_compiler)] -struct QueryLatchInfo { +struct QueryLatchInfo { complete: bool, - waiters: Vec>, + waiters: Vec>>, } #[cfg(parallel_compiler)] #[derive(Clone)] -pub(super) struct QueryLatch { - info: Lrc>, +pub(super) struct QueryLatch { + info: Lrc>>, } #[cfg(parallel_compiler)] -impl QueryLatch { +impl QueryLatch { fn new() -> Self { QueryLatch { info: Lrc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -216,7 +224,11 @@ fn new() -> Self { } /// Awaits for the query job to complete. - pub(super) fn wait_on(&self, query: Option, span: Span) -> Result<(), CycleError> { + pub(super) fn wait_on( + &self, + query: Option, + span: Span, + ) -> Result<(), CycleError> { let waiter = Lrc::new(QueryWaiter { query, span, cycle: Lock::new(None), condvar: Condvar::new() }); self.wait_on_inner(&waiter); @@ -231,7 +243,7 @@ pub(super) fn wait_on(&self, query: Option, span: Span) -> Result<() } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, waiter: &Lrc) { + fn wait_on_inner(&self, waiter: &Lrc>) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -265,7 +277,7 @@ fn set(&self) { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Lrc { + fn extract_waiter(&self, waiter: usize) -> Lrc> { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -287,9 +299,14 @@ fn extract_waiter(&self, waiter: usize) -> Lrc { /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. #[cfg(parallel_compiler)] -fn visit_waiters(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Option> +fn visit_waiters( + query_map: &QueryMap, + query: QueryJobId, + mut visit: F, +) -> Option> where F: FnMut(Span, QueryJobId) -> Option>, + D: DepKind, { // Visit the parent query which is a non-resumable waiter since it's on the same stack if let Some(parent) = query.parent(query_map) { @@ -318,8 +335,8 @@ fn visit_waiters(query_map: &QueryMap, query: QueryJobId, mut visit: F) -> Op /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. #[cfg(parallel_compiler)] -fn cycle_check( - query_map: &QueryMap, +fn cycle_check( + query_map: &QueryMap, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -359,8 +376,8 @@ fn cycle_check( /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. #[cfg(parallel_compiler)] -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root( + query_map: &QueryMap, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -382,9 +399,10 @@ fn connected_to_root( // Deterministically pick an query from a list #[cfg(parallel_compiler)] -fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, T, F, D>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), + D: DepKind, { // Deterministically pick an entry point // FIXME: Sort this instead @@ -408,10 +426,10 @@ fn pick_query<'a, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. #[cfg(parallel_compiler)] -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle( + query_map: &QueryMap, jobs: &mut Vec, - wakelist: &mut Vec>, + wakelist: &mut Vec>>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -513,7 +531,7 @@ fn remove_cycle( /// 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. #[cfg(parallel_compiler)] -pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { +pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { let on_panic = OnDrop(|| { eprintln!("deadlock handler panicked, aborting process"); process::abort(); @@ -549,9 +567,9 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) { #[inline(never)] #[cold] -pub(crate) fn report_cycle<'a>( +pub(crate) fn report_cycle<'a, D: DepKind>( sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, + CycleError { usage, cycle: stack }: &CycleError, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { assert!(!stack.is_empty()); @@ -617,7 +635,7 @@ pub fn print_query_stack( }; let mut diag = Diagnostic::new( Level::FailureNote, - &format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description), + &format!("#{} [{:?}] {}", i, query_info.query.dep_kind, query_info.query.description), ); diag.span = query_info.job.span.into(); handler.force_print_diagnostic(diag); diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 7f3dc50d234..ce9179ea832 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -14,6 +14,7 @@ mod config; pub use self::config::{QueryConfig, QueryVTable}; +use crate::dep_graph::DepKind; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; use rustc_errors::Diagnostic; @@ -26,37 +27,37 @@ /// /// This is mostly used in case of cycles for error reporting. #[derive(Clone, Debug)] -pub struct QueryStackFrame { - pub name: &'static str, +pub struct QueryStackFrame { pub description: String, span: Option, pub def_id: Option, pub def_kind: Option, pub ty_adt_id: Option, + pub dep_kind: D, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. #[cfg(parallel_compiler)] hash: u64, } -impl QueryStackFrame { +impl QueryStackFrame { #[inline] pub fn new( - name: &'static str, description: String, span: Option, def_id: Option, def_kind: Option, + dep_kind: D, ty_adt_id: Option, _hash: impl FnOnce() -> u64, ) -> Self { Self { - name, description, span, def_id, def_kind, ty_adt_id, + dep_kind, #[cfg(parallel_compiler)] hash: _hash(), } @@ -104,7 +105,7 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(&self) -> Option; - fn try_collect_active_jobs(&self) -> Option; + fn try_collect_active_jobs(&self) -> Option>; /// Load side effects associated to the node in the previous session. fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 848fa67e3df..c3a2410daca 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,7 +2,7 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams}; +use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::config::QueryVTable; @@ -31,26 +31,27 @@ use super::QueryConfig; -pub struct QueryState { +pub struct QueryState { #[cfg(parallel_compiler)] - active: Sharded>, + active: Sharded>>, #[cfg(not(parallel_compiler))] - active: Lock>, + active: Lock>>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryState +impl QueryState where K: Eq + Hash + Clone + Debug, + D: DepKind, { pub fn all_inactive(&self) -> bool { #[cfg(parallel_compiler)] @@ -67,8 +68,8 @@ pub fn all_inactive(&self) -> bool { pub fn try_collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame, + jobs: &mut QueryMap, ) -> Option<()> { #[cfg(parallel_compiler)] { @@ -102,34 +103,34 @@ pub fn try_collect_active_jobs( } } -impl Default for QueryState { - fn default() -> QueryState { +impl Default for QueryState { + fn default() -> QueryState { 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> +struct JobOwner<'tcx, K, D: DepKind> where K: Eq + Hash + Clone, { - state: &'tcx QueryState, + state: &'tcx QueryState, key: K, id: QueryJobId, } #[cold] #[inline(never)] -fn mk_cycle( +fn mk_cycle( qcx: Qcx, - cycle_error: CycleError, + cycle_error: CycleError, handler: HandleCycleError, cache: &dyn crate::query::QueryStorage, ) -> R where - Qcx: QueryContext, - V: std::fmt::Debug + Value, + Qcx: QueryContext + crate::query::HasDepContext, + V: std::fmt::Debug + Value, R: Clone, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); @@ -139,13 +140,13 @@ fn mk_cycle( fn handle_cycle_error( tcx: Tcx, - cycle_error: &CycleError, + cycle_error: &CycleError, mut error: DiagnosticBuilder<'_, ErrorGuaranteed>, handler: HandleCycleError, ) -> V where Tcx: DepContext, - V: Value, + V: Value, { use HandleCycleError::*; match handler { @@ -165,7 +166,7 @@ fn handle_cycle_error( } } -impl<'tcx, K> JobOwner<'tcx, K> +impl<'tcx, K, D: DepKind> JobOwner<'tcx, K, D> where K: Eq + Hash + Clone, { @@ -180,12 +181,12 @@ impl<'tcx, K> JobOwner<'tcx, K> #[inline(always)] fn try_start<'b, Qcx>( qcx: &'b Qcx, - state: &'b QueryState, + state: &'b QueryState, span: Span, key: K, - ) -> TryGetJob<'b, K> + ) -> TryGetJob<'b, K, D> where - Qcx: QueryContext, + Qcx: QueryContext + crate::query::HasDepContext, { #[cfg(parallel_compiler)] let mut state_lock = state.active.get_shard_by_value(&key).lock(); @@ -280,9 +281,10 @@ fn complete(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) } } -impl<'tcx, K> Drop for JobOwner<'tcx, K> +impl<'tcx, K, D> Drop for JobOwner<'tcx, K, D> where K: Eq + Hash + Clone, + D: DepKind, { #[inline(never)] #[cold] @@ -308,19 +310,20 @@ fn drop(&mut self) { } #[derive(Clone)] -pub(crate) struct CycleError { +pub(crate) struct CycleError { /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec, + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec>, } /// The result of `try_start`. -enum TryGetJob<'tcx, K> +enum TryGetJob<'tcx, K, D> where K: Eq + Hash + Clone, + D: DepKind, { /// The query is not yet started. Contains a guard to the cache eventually used to start it. - NotYetStarted(JobOwner<'tcx, K>), + NotYetStarted(JobOwner<'tcx, K, D>), /// The query was already completed. /// Returns the result of the query and its dep-node index @@ -329,7 +332,7 @@ enum TryGetJob<'tcx, K> JobCompleted(TimingGuard<'tcx>), /// Trying to execute the query resulted in a cycle. - Cycle(CycleError), + Cycle(CycleError), } /// Checks if the query is already computed and in the cache. @@ -360,7 +363,7 @@ pub fn try_get_cached<'a, Tcx, C, R, OnHit>( fn try_execute_query( qcx: Qcx, - state: &QueryState, + state: &QueryState, cache: &C, span: Span, key: C::Key, @@ -370,11 +373,11 @@ fn try_execute_query( where C: QueryCache, C::Key: Clone + DepNodeParams, - C::Value: Value, + C::Value: Value, C::Stored: Debug + std::borrow::Borrow, Qcx: QueryContext, { - match JobOwner::<'_, C::Key>::try_start(&qcx, state, span, key.clone()) { + match JobOwner::<'_, C::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { let (result, dep_node_index) = execute_job(qcx, key.clone(), dep_node, query, job.id); if query.feedable { @@ -739,11 +742,12 @@ pub enum QueryMode { Ensure, } -pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option +pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option where + D: DepKind, Q: QueryConfig, Q::Key: DepNodeParams, - Q::Value: Value, + Q::Value: Value, Qcx: QueryContext, { let query = Q::make_vtable(qcx, &key); @@ -772,11 +776,12 @@ pub fn get_query(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Some(result) } -pub fn force_query(qcx: Qcx, key: Q::Key, dep_node: DepNode) +pub fn force_query(qcx: Qcx, key: Q::Key, dep_node: DepNode) where + D: DepKind, Q: QueryConfig, Q::Key: DepNodeParams, - Q::Value: Value, + Q::Value: Value, Qcx: QueryContext, { // We may be concurrently trying both execute and force a query. diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs index 214656abed4..b6e2cfa3dca 100644 --- a/compiler/rustc_query_system/src/values.rs +++ b/compiler/rustc_query_system/src/values.rs @@ -1,12 +1,12 @@ -use crate::dep_graph::DepContext; +use crate::dep_graph::{DepContext, DepKind}; use crate::query::QueryInfo; -pub trait Value: Sized { - fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self; +pub trait Value: Sized { + fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo]) -> Self; } -impl Value for T { - default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T { +impl Value for T { + default fn from_cycle_error(tcx: Tcx, _: &[QueryInfo]) -> T { tcx.sess().abort_if_errors(); // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's // non-trivial to define it earlier.