Auto merge of #122156 - Zoxc:side-effect-dep-node, r=oli-obk
Represent diagnostic side effects as dep nodes This changes diagnostic to be tracked as a special dep node (`SideEffect`) instead of having a list of side effects associated with each dep node. `SideEffect` is always red and when forced, it emits the diagnostic and marks itself green. Each emitted diagnostic generates a new `SideEffect` with an unique dep node index. Some implications of this: - Diagnostic may now be emitted more than once as they can be emitted once when the `SideEffect` gets marked green and again if the task it depends on needs to be re-executed due to another node being red. It relies on deduplicating of diagnostics to avoid that. - Anon tasks which emits diagnostics will no longer *incorrectly* be merged with other anon tasks. - Reusing a CGU will now emit diagnostics from the task generating it.
This commit is contained in:
commit
1aeb99d248
12 changed files with 185 additions and 206 deletions
|
@ -14,6 +14,7 @@ use std::fmt;
|
||||||
use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC};
|
use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC};
|
||||||
use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef};
|
use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef};
|
||||||
use rustc_middle::ty::tls;
|
use rustc_middle::ty::tls;
|
||||||
|
use rustc_query_impl::QueryCtxt;
|
||||||
use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug;
|
use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug;
|
||||||
use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode};
|
use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode};
|
||||||
|
|
||||||
|
@ -41,9 +42,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
|
||||||
fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
|
fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
|
||||||
tls::with_context_opt(|icx| {
|
tls::with_context_opt(|icx| {
|
||||||
if let Some(icx) = icx {
|
if let Some(icx) = icx {
|
||||||
if let Some(diagnostics) = icx.diagnostics {
|
icx.tcx.dep_graph.record_diagnostic(QueryCtxt::new(icx.tcx), &diagnostic);
|
||||||
diagnostics.lock().extend(Some(diagnostic.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Diagnostics are tracked, we can ignore the dependency.
|
// Diagnostics are tracked, we can ignore the dependency.
|
||||||
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };
|
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };
|
||||||
|
|
|
@ -79,6 +79,7 @@ rustc_query_append!(define_dep_nodes![
|
||||||
[] fn Null() -> (),
|
[] fn Null() -> (),
|
||||||
/// We use this to create a forever-red node.
|
/// We use this to create a forever-red node.
|
||||||
[] fn Red() -> (),
|
[] fn Red() -> (),
|
||||||
|
[] fn SideEffect() -> (),
|
||||||
[] fn TraitSelect() -> (),
|
[] fn TraitSelect() -> (),
|
||||||
[] fn CompileCodegenUnit() -> (),
|
[] fn CompileCodegenUnit() -> (),
|
||||||
[] fn CompileMonoItem() -> (),
|
[] fn CompileMonoItem() -> (),
|
||||||
|
|
|
@ -46,6 +46,7 @@ impl Deps for DepsType {
|
||||||
|
|
||||||
const DEP_KIND_NULL: DepKind = dep_kinds::Null;
|
const DEP_KIND_NULL: DepKind = dep_kinds::Null;
|
||||||
const DEP_KIND_RED: DepKind = dep_kinds::Red;
|
const DEP_KIND_RED: DepKind = dep_kinds::Red;
|
||||||
|
const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect;
|
||||||
const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
|
const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab
|
||||||
use rustc_hir::definitions::DefPathHash;
|
use rustc_hir::definitions::DefPathHash;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable, Encodable};
|
||||||
use rustc_query_system::query::QuerySideEffects;
|
use rustc_query_system::query::QuerySideEffect;
|
||||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
@ -55,9 +55,9 @@ pub struct OnDiskCache {
|
||||||
// The complete cache data in serialized form.
|
// The complete cache data in serialized form.
|
||||||
serialized_data: RwLock<Option<Mmap>>,
|
serialized_data: RwLock<Option<Mmap>>,
|
||||||
|
|
||||||
// Collects all `QuerySideEffects` created during the current compilation
|
// Collects all `QuerySideEffect` created during the current compilation
|
||||||
// session.
|
// session.
|
||||||
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
|
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffect>>,
|
||||||
|
|
||||||
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ pub struct OnDiskCache {
|
||||||
// `serialized_data`.
|
// `serialized_data`.
|
||||||
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
||||||
|
|
||||||
// A map from dep-node to the position of any associated `QuerySideEffects` in
|
// A map from dep-node to the position of any associated `QuerySideEffect` in
|
||||||
// `serialized_data`.
|
// `serialized_data`.
|
||||||
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
|
||||||
|
|
||||||
|
@ -270,10 +270,10 @@ impl OnDiskCache {
|
||||||
.current_side_effects
|
.current_side_effects
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(dep_node_index, side_effects)| {
|
.map(|(dep_node_index, side_effect)| {
|
||||||
let pos = AbsoluteBytePos::new(encoder.position());
|
let pos = AbsoluteBytePos::new(encoder.position());
|
||||||
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
|
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
|
||||||
encoder.encode_tagged(dep_node_index, side_effects);
|
encoder.encode_tagged(dep_node_index, side_effect);
|
||||||
|
|
||||||
(dep_node_index, pos)
|
(dep_node_index, pos)
|
||||||
})
|
})
|
||||||
|
@ -352,24 +352,23 @@ impl OnDiskCache {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a `QuerySideEffects` created during the previous compilation session.
|
/// Loads a `QuerySideEffect` created during the previous compilation session.
|
||||||
pub fn load_side_effects(
|
pub fn load_side_effect(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
dep_node_index: SerializedDepNodeIndex,
|
dep_node_index: SerializedDepNodeIndex,
|
||||||
) -> QuerySideEffects {
|
) -> Option<QuerySideEffect> {
|
||||||
let side_effects: Option<QuerySideEffects> =
|
let side_effect: Option<QuerySideEffect> =
|
||||||
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
|
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
|
||||||
|
side_effect
|
||||||
side_effects.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores a `QuerySideEffects` emitted during the current compilation session.
|
/// Stores a `QuerySideEffect` emitted during the current compilation session.
|
||||||
/// Anything stored like this will be available via `load_side_effects` in
|
/// Anything stored like this will be available via `load_side_effect` in
|
||||||
/// the next compilation session.
|
/// the next compilation session.
|
||||||
pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
|
pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
|
||||||
let mut current_side_effects = self.current_side_effects.borrow_mut();
|
let mut current_side_effects = self.current_side_effects.borrow_mut();
|
||||||
let prev = current_side_effects.insert(dep_node_index, side_effects);
|
let prev = current_side_effects.insert(dep_node_index, side_effect);
|
||||||
debug_assert!(prev.is_none());
|
debug_assert!(prev.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,21 +394,6 @@ impl OnDiskCache {
|
||||||
opt_value
|
opt_value
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores side effect emitted during computation of an anonymous query.
|
|
||||||
/// Since many anonymous queries can share the same `DepNode`, we aggregate
|
|
||||||
/// them -- as opposed to regular queries where we assume that there is a
|
|
||||||
/// 1:1 relationship between query-key and `DepNode`.
|
|
||||||
pub fn store_side_effects_for_anon_node(
|
|
||||||
&self,
|
|
||||||
dep_node_index: DepNodeIndex,
|
|
||||||
side_effects: QuerySideEffects,
|
|
||||||
) {
|
|
||||||
let mut current_side_effects = self.current_side_effects.borrow_mut();
|
|
||||||
|
|
||||||
let x = current_side_effects.entry(dep_node_index).or_default();
|
|
||||||
x.append(side_effects);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_indexed<'tcx, T>(
|
fn load_indexed<'tcx, T>(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
use rustc_data_structures::sync::{self, Lock};
|
use rustc_data_structures::sync;
|
||||||
use rustc_errors::DiagInner;
|
|
||||||
use thin_vec::ThinVec;
|
|
||||||
|
|
||||||
use super::{GlobalCtxt, TyCtxt};
|
use super::{GlobalCtxt, TyCtxt};
|
||||||
use crate::dep_graph::TaskDepsRef;
|
use crate::dep_graph::TaskDepsRef;
|
||||||
|
@ -22,10 +20,6 @@ pub struct ImplicitCtxt<'a, 'tcx> {
|
||||||
/// `ty::query::plumbing` when executing a query.
|
/// `ty::query::plumbing` when executing a query.
|
||||||
pub query: Option<QueryJobId>,
|
pub query: Option<QueryJobId>,
|
||||||
|
|
||||||
/// Where to store diagnostics for the current query job, if any.
|
|
||||||
/// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
|
|
||||||
pub diagnostics: Option<&'a Lock<ThinVec<DiagInner>>>,
|
|
||||||
|
|
||||||
/// Used to prevent queries from calling too deeply.
|
/// Used to prevent queries from calling too deeply.
|
||||||
pub query_depth: usize,
|
pub query_depth: usize,
|
||||||
|
|
||||||
|
@ -37,13 +31,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
|
||||||
impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
|
||||||
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
|
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
|
||||||
let tcx = TyCtxt { gcx };
|
let tcx = TyCtxt { gcx };
|
||||||
ImplicitCtxt {
|
ImplicitCtxt { tcx, query: None, query_depth: 0, task_deps: TaskDepsRef::Ignore }
|
||||||
tcx,
|
|
||||||
query: None,
|
|
||||||
diagnostics: None,
|
|
||||||
query_depth: 0,
|
|
||||||
task_deps: TaskDepsRef::Ignore,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::Lock;
|
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::UnordMap;
|
||||||
use rustc_errors::DiagInner;
|
|
||||||
use rustc_hashes::Hash64;
|
use rustc_hashes::Hash64;
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
|
@ -26,14 +24,13 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
|
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_query_system::query::{
|
use rustc_query_system::query::{
|
||||||
QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
|
QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame,
|
||||||
force_query,
|
force_query,
|
||||||
};
|
};
|
||||||
use rustc_query_system::{QueryOverflow, QueryOverflowNote};
|
use rustc_query_system::{QueryOverflow, QueryOverflowNote};
|
||||||
use rustc_serialize::{Decodable, Encodable};
|
use rustc_serialize::{Decodable, Encodable};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use thin_vec::ThinVec;
|
|
||||||
|
|
||||||
use crate::QueryConfigRestored;
|
use crate::QueryConfigRestored;
|
||||||
|
|
||||||
|
@ -93,43 +90,31 @@ impl QueryContext for QueryCtxt<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interactions with on_disk_cache
|
// Interactions with on_disk_cache
|
||||||
fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
|
fn load_side_effect(
|
||||||
|
self,
|
||||||
|
prev_dep_node_index: SerializedDepNodeIndex,
|
||||||
|
) -> Option<QuerySideEffect> {
|
||||||
self.query_system
|
self.query_system
|
||||||
.on_disk_cache
|
.on_disk_cache
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|c| c.load_side_effects(self.tcx, prev_dep_node_index))
|
.and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[cold]
|
#[cold]
|
||||||
fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
|
fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
|
||||||
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
|
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
|
||||||
c.store_side_effects(dep_node_index, side_effects)
|
c.store_side_effect(dep_node_index, side_effect)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(never)]
|
|
||||||
#[cold]
|
|
||||||
fn store_side_effects_for_anon_node(
|
|
||||||
self,
|
|
||||||
dep_node_index: DepNodeIndex,
|
|
||||||
side_effects: QuerySideEffects,
|
|
||||||
) {
|
|
||||||
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
|
|
||||||
c.store_side_effects_for_anon_node(dep_node_index, side_effects)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a job by changing the `ImplicitCtxt` to point to the
|
/// Executes a job by changing the `ImplicitCtxt` to point to the
|
||||||
/// new query job while it executes. It returns the diagnostics
|
/// new query job while it executes.
|
||||||
/// captured during execution and the actual result.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn start_query<R>(
|
fn start_query<R>(
|
||||||
self,
|
self,
|
||||||
token: QueryJobId,
|
token: QueryJobId,
|
||||||
depth_limit: bool,
|
depth_limit: bool,
|
||||||
diagnostics: Option<&Lock<ThinVec<DiagInner>>>,
|
|
||||||
compute: impl FnOnce() -> R,
|
compute: impl FnOnce() -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
// The `TyCtxt` stored in TLS has the same global interner lifetime
|
// The `TyCtxt` stored in TLS has the same global interner lifetime
|
||||||
|
@ -144,7 +129,6 @@ impl QueryContext for QueryCtxt<'_> {
|
||||||
let new_icx = ImplicitCtxt {
|
let new_icx = ImplicitCtxt {
|
||||||
tcx: self.tcx,
|
tcx: self.tcx,
|
||||||
query: Some(token),
|
query: Some(token),
|
||||||
diagnostics,
|
|
||||||
query_depth: current_icx.query_depth + depth_limit as usize,
|
query_depth: current_icx.query_depth + depth_limit as usize,
|
||||||
task_deps: current_icx.task_deps,
|
task_deps: current_icx.task_deps,
|
||||||
};
|
};
|
||||||
|
@ -501,7 +485,7 @@ where
|
||||||
is_anon,
|
is_anon,
|
||||||
is_eval_always,
|
is_eval_always,
|
||||||
fingerprint_style,
|
fingerprint_style,
|
||||||
force_from_dep_node: Some(|tcx, dep_node| {
|
force_from_dep_node: Some(|tcx, dep_node, _| {
|
||||||
force_from_dep_node(Q::config(tcx), tcx, dep_node)
|
force_from_dep_node(Q::config(tcx), tcx, dep_node)
|
||||||
}),
|
}),
|
||||||
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
|
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
|
||||||
|
@ -803,7 +787,7 @@ macro_rules! define_queries {
|
||||||
is_anon: false,
|
is_anon: false,
|
||||||
is_eval_always: false,
|
is_eval_always: false,
|
||||||
fingerprint_style: FingerprintStyle::Unit,
|
fingerprint_style: FingerprintStyle::Unit,
|
||||||
force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
|
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
|
||||||
try_load_from_on_disk_cache: None,
|
try_load_from_on_disk_cache: None,
|
||||||
name: &"Null",
|
name: &"Null",
|
||||||
}
|
}
|
||||||
|
@ -815,12 +799,26 @@ macro_rules! define_queries {
|
||||||
is_anon: false,
|
is_anon: false,
|
||||||
is_eval_always: false,
|
is_eval_always: false,
|
||||||
fingerprint_style: FingerprintStyle::Unit,
|
fingerprint_style: FingerprintStyle::Unit,
|
||||||
force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
|
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
|
||||||
try_load_from_on_disk_cache: None,
|
try_load_from_on_disk_cache: None,
|
||||||
name: &"Red",
|
name: &"Red",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn SideEffect<'tcx>() -> DepKindStruct<'tcx> {
|
||||||
|
DepKindStruct {
|
||||||
|
is_anon: false,
|
||||||
|
is_eval_always: false,
|
||||||
|
fingerprint_style: FingerprintStyle::Unit,
|
||||||
|
force_from_dep_node: Some(|tcx, _, prev_index| {
|
||||||
|
tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
|
||||||
|
true
|
||||||
|
}),
|
||||||
|
try_load_from_on_disk_cache: None,
|
||||||
|
name: &"SideEffect",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
|
pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
|
||||||
DepKindStruct {
|
DepKindStruct {
|
||||||
is_anon: true,
|
is_anon: true,
|
||||||
|
|
|
@ -64,7 +64,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd,
|
||||||
use rustc_hir::definitions::DefPathHash;
|
use rustc_hir::definitions::DefPathHash;
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable, Encodable};
|
||||||
|
|
||||||
use super::{DepContext, FingerprintStyle};
|
use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex};
|
||||||
use crate::ich::StableHashingContext;
|
use crate::ich::StableHashingContext;
|
||||||
|
|
||||||
/// This serves as an index into arrays built by `make_dep_kind_array`.
|
/// This serves as an index into arrays built by `make_dep_kind_array`.
|
||||||
|
@ -275,7 +275,8 @@ pub struct DepKindStruct<Tcx: DepContext> {
|
||||||
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
||||||
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
||||||
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
||||||
pub force_from_dep_node: Option<fn(tcx: Tcx, dep_node: DepNode) -> bool>,
|
pub force_from_dep_node:
|
||||||
|
Option<fn(tcx: Tcx, dep_node: DepNode, prev_index: SerializedDepNodeIndex) -> bool>,
|
||||||
|
|
||||||
/// Invoke a query to put the on-disk cached value in memory.
|
/// Invoke a query to put the on-disk cached value in memory.
|
||||||
pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode)>,
|
pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode)>,
|
||||||
|
|
|
@ -5,13 +5,14 @@ use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
|
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
|
||||||
use rustc_data_structures::sharded::{self, ShardedHashMap};
|
use rustc_data_structures::sharded::{self, ShardedHashMap};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::sync::{AtomicU64, Lock};
|
use rustc_data_structures::sync::{AtomicU64, Lock};
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::UnordMap;
|
||||||
|
use rustc_errors::DiagInner;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable, Encodable};
|
||||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||||
|
@ -24,7 +25,7 @@ use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex
|
||||||
use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId};
|
use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId};
|
||||||
use crate::dep_graph::edges::EdgesVec;
|
use crate::dep_graph::edges::EdgesVec;
|
||||||
use crate::ich::StableHashingContext;
|
use crate::ich::StableHashingContext;
|
||||||
use crate::query::{QueryContext, QuerySideEffects};
|
use crate::query::{QueryContext, QuerySideEffect};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DepGraph<D: Deps> {
|
pub struct DepGraph<D: Deps> {
|
||||||
|
@ -91,8 +92,6 @@ pub(crate) struct DepGraphData<D: Deps> {
|
||||||
|
|
||||||
colors: DepNodeColorMap,
|
colors: DepNodeColorMap,
|
||||||
|
|
||||||
processed_side_effects: Lock<FxHashSet<DepNodeIndex>>,
|
|
||||||
|
|
||||||
/// When we load, there may be `.o` files, cached MIR, or other such
|
/// When we load, there may be `.o` files, cached MIR, or other such
|
||||||
/// things available to us. If we find that they are not dirty, we
|
/// things available to us. If we find that they are not dirty, we
|
||||||
/// load the path to the file storing those work-products here into
|
/// load the path to the file storing those work-products here into
|
||||||
|
@ -174,7 +173,6 @@ impl<D: Deps> DepGraph<D> {
|
||||||
previous_work_products: prev_work_products,
|
previous_work_products: prev_work_products,
|
||||||
dep_node_debug: Default::default(),
|
dep_node_debug: Default::default(),
|
||||||
current,
|
current,
|
||||||
processed_side_effects: Default::default(),
|
|
||||||
previous: prev_graph,
|
previous: prev_graph,
|
||||||
colors,
|
colors,
|
||||||
debug_loaded_from_disk: Default::default(),
|
debug_loaded_from_disk: Default::default(),
|
||||||
|
@ -535,6 +533,32 @@ impl<D: Deps> DepGraph<D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This encodes a diagnostic by creating a node with an unique index and assoicating
|
||||||
|
/// `diagnostic` with it, for use in the next session.
|
||||||
|
#[inline]
|
||||||
|
pub fn record_diagnostic<Qcx: QueryContext>(&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,
|
||||||
|
TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => {
|
||||||
|
self.read_index(data.encode_diagnostic(qcx, diagnostic));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// 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<Qcx: QueryContext>(
|
||||||
|
&self,
|
||||||
|
qcx: Qcx,
|
||||||
|
prev_index: SerializedDepNodeIndex,
|
||||||
|
) {
|
||||||
|
if let Some(ref data) = self.data {
|
||||||
|
data.force_diagnostic_node(qcx, prev_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a node when we force-feed a value into the query cache.
|
/// Create a node when we force-feed a value into the query cache.
|
||||||
/// This is used to remove cycles during type-checking const generic parameters.
|
/// This is used to remove cycles during type-checking const generic parameters.
|
||||||
///
|
///
|
||||||
|
@ -656,6 +680,57 @@ impl<D: Deps> DepGraphData<D> {
|
||||||
pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) {
|
pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) {
|
||||||
self.debug_loaded_from_disk.lock().insert(dep_node);
|
self.debug_loaded_from_disk.lock().insert(dep_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This encodes a diagnostic by creating a node with an unique index and assoicating
|
||||||
|
/// `diagnostic` with it, for use in the next session.
|
||||||
|
#[inline]
|
||||||
|
fn encode_diagnostic<Qcx: QueryContext>(
|
||||||
|
&self,
|
||||||
|
qcx: Qcx,
|
||||||
|
diagnostic: &DiagInner,
|
||||||
|
) -> DepNodeIndex {
|
||||||
|
// Use `send` so we get an unique index, even though the dep node is not.
|
||||||
|
let dep_node_index = self.current.encoder.send(
|
||||||
|
DepNode {
|
||||||
|
kind: D::DEP_KIND_SIDE_EFFECT,
|
||||||
|
hash: PackedFingerprint::from(Fingerprint::ZERO),
|
||||||
|
},
|
||||||
|
Fingerprint::ZERO,
|
||||||
|
// We want the side effect node to always be red so it will be forced and emit the
|
||||||
|
// diagnostic.
|
||||||
|
std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
|
||||||
|
);
|
||||||
|
let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone());
|
||||||
|
qcx.store_side_effect(dep_node_index, side_effect);
|
||||||
|
dep_node_index
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<Qcx: QueryContext>(
|
||||||
|
&self,
|
||||||
|
qcx: Qcx,
|
||||||
|
prev_index: SerializedDepNodeIndex,
|
||||||
|
) {
|
||||||
|
D::with_deps(TaskDepsRef::Ignore, || {
|
||||||
|
let side_effect = qcx.load_side_effect(prev_index).unwrap();
|
||||||
|
|
||||||
|
match &side_effect {
|
||||||
|
QuerySideEffect::Diagnostic(diagnostic) => {
|
||||||
|
qcx.dep_context().sess().dcx().emit_diagnostic(diagnostic.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Promote the previous diagnostics to the current session.
|
||||||
|
let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index);
|
||||||
|
// FIXME: Can this race with a parallel compiler?
|
||||||
|
qcx.store_side_effect(index, side_effect);
|
||||||
|
|
||||||
|
// Mark the node as green.
|
||||||
|
self.colors.insert(prev_index, DepNodeColor::Green(index));
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Deps> DepGraph<D> {
|
impl<D: Deps> DepGraph<D> {
|
||||||
|
@ -794,7 +869,7 @@ impl<D: Deps> DepGraphData<D> {
|
||||||
|
|
||||||
// We failed to mark it green, so we try to force the query.
|
// We failed to mark it green, so we try to force the query.
|
||||||
debug!("trying to force dependency {dep_dep_node:?}");
|
debug!("trying to force dependency {dep_dep_node:?}");
|
||||||
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) {
|
if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) {
|
||||||
// The DepNode could not be forced.
|
// The DepNode could not be forced.
|
||||||
debug!("dependency {dep_dep_node:?} could not be forced");
|
debug!("dependency {dep_dep_node:?} could not be forced");
|
||||||
return None;
|
return None;
|
||||||
|
@ -867,16 +942,6 @@ impl<D: Deps> DepGraphData<D> {
|
||||||
|
|
||||||
// ... emitting any stored diagnostic ...
|
// ... emitting any stored diagnostic ...
|
||||||
|
|
||||||
// FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
|
|
||||||
// Maybe store a list on disk and encode this fact in the DepNodeState
|
|
||||||
let side_effects = qcx.load_side_effects(prev_dep_node_index);
|
|
||||||
|
|
||||||
if side_effects.maybe_any() {
|
|
||||||
qcx.dep_context().dep_graph().with_query_deserialization(|| {
|
|
||||||
self.emit_side_effects(qcx, dep_node_index, side_effects)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... and finally storing a "Green" entry in the color map.
|
// ... and finally storing a "Green" entry in the color map.
|
||||||
// Multiple threads can all write the same color here
|
// Multiple threads can all write the same color here
|
||||||
self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
|
self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
|
||||||
|
@ -884,33 +949,6 @@ impl<D: Deps> DepGraphData<D> {
|
||||||
debug!("successfully marked {dep_node:?} as green");
|
debug!("successfully marked {dep_node:?} as green");
|
||||||
Some(dep_node_index)
|
Some(dep_node_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Atomically emits some loaded diagnostics.
|
|
||||||
/// This may be called concurrently on multiple threads for the same dep node.
|
|
||||||
#[cold]
|
|
||||||
#[inline(never)]
|
|
||||||
fn emit_side_effects<Qcx: QueryContext<Deps = D>>(
|
|
||||||
&self,
|
|
||||||
qcx: Qcx,
|
|
||||||
dep_node_index: DepNodeIndex,
|
|
||||||
side_effects: QuerySideEffects,
|
|
||||||
) {
|
|
||||||
let mut processed = self.processed_side_effects.lock();
|
|
||||||
|
|
||||||
if processed.insert(dep_node_index) {
|
|
||||||
// We were the first to insert the node in the set so this thread
|
|
||||||
// must process side effects
|
|
||||||
|
|
||||||
// Promote the previous diagnostics to the current session.
|
|
||||||
qcx.store_side_effects(dep_node_index, side_effects.clone());
|
|
||||||
|
|
||||||
let dcx = qcx.dep_context().sess().dcx();
|
|
||||||
|
|
||||||
for diagnostic in side_effects.diagnostics {
|
|
||||||
dcx.emit_diagnostic(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Deps> DepGraph<D> {
|
impl<D: Deps> DepGraph<D> {
|
||||||
|
|
|
@ -58,10 +58,15 @@ pub trait DepContext: Copy {
|
||||||
/// dep-node or when the query kind outright does not support it.
|
/// dep-node or when the query kind outright does not support it.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[instrument(skip(self, frame), level = "debug")]
|
#[instrument(skip(self, frame), level = "debug")]
|
||||||
fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool {
|
fn try_force_from_dep_node(
|
||||||
|
self,
|
||||||
|
dep_node: DepNode,
|
||||||
|
prev_index: SerializedDepNodeIndex,
|
||||||
|
frame: Option<&MarkFrame<'_>>,
|
||||||
|
) -> bool {
|
||||||
let cb = self.dep_kind_info(dep_node.kind);
|
let cb = self.dep_kind_info(dep_node.kind);
|
||||||
if let Some(f) = cb.force_from_dep_node {
|
if let Some(f) = cb.force_from_dep_node {
|
||||||
match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node))) {
|
match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node, prev_index))) {
|
||||||
Err(value) => {
|
Err(value) => {
|
||||||
if !value.is::<rustc_errors::FatalErrorMarker>() {
|
if !value.is::<rustc_errors::FatalErrorMarker>() {
|
||||||
print_markframe_trace(self.dep_graph(), frame);
|
print_markframe_trace(self.dep_graph(), frame);
|
||||||
|
@ -101,6 +106,9 @@ pub trait Deps {
|
||||||
/// We use this to create a forever-red node.
|
/// We use this to create a forever-red node.
|
||||||
const DEP_KIND_RED: DepKind;
|
const DEP_KIND_RED: DepKind;
|
||||||
|
|
||||||
|
/// We use this to create a side effect node.
|
||||||
|
const DEP_KIND_SIDE_EFFECT: DepKind;
|
||||||
|
|
||||||
/// This is the highest value a `DepKind` can have. It's used during encoding to
|
/// This is the highest value a `DepKind` can have. It's used during encoding to
|
||||||
/// pack information into the unused bits.
|
/// pack information into the unused bits.
|
||||||
const DEP_KIND_MAX: u16;
|
const DEP_KIND_MAX: u16;
|
||||||
|
|
|
@ -11,14 +11,12 @@ mod caches;
|
||||||
pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
|
pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
use rustc_data_structures::sync::Lock;
|
|
||||||
use rustc_errors::DiagInner;
|
use rustc_errors::DiagInner;
|
||||||
use rustc_hashes::Hash64;
|
use rustc_hashes::Hash64;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_macros::{Decodable, Encodable};
|
use rustc_macros::{Decodable, Encodable};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use thin_vec::ThinVec;
|
|
||||||
|
|
||||||
pub use self::config::{HashResult, QueryConfig};
|
pub use self::config::{HashResult, QueryConfig};
|
||||||
use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
|
use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
|
||||||
|
@ -64,33 +62,22 @@ impl QueryStackFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracks 'side effects' for a particular query.
|
/// Track a 'side effects' for a particular query.
|
||||||
/// This struct is saved to disk along with the query result,
|
/// This struct is saved to disk along with the query result,
|
||||||
/// and loaded from disk if we mark the query as green.
|
/// and loaded from disk if we mark the query as green.
|
||||||
/// This allows us to 'replay' changes to global state
|
/// This allows us to 'replay' changes to global state
|
||||||
/// that would otherwise only occur if we actually
|
/// that would otherwise only occur if we actually
|
||||||
/// executed the query method.
|
/// executed the query method.
|
||||||
#[derive(Debug, Clone, Default, Encodable, Decodable)]
|
///
|
||||||
pub struct QuerySideEffects {
|
/// Each side effect gets an unique dep node index which is added
|
||||||
/// Stores any diagnostics emitted during query execution.
|
/// as a dependency of the query which had the effect.
|
||||||
/// These diagnostics will be re-emitted if we mark
|
#[derive(Debug, Encodable, Decodable)]
|
||||||
/// the query as green.
|
pub enum QuerySideEffect {
|
||||||
pub(super) diagnostics: ThinVec<DiagInner>,
|
/// Stores a diagnostic emitted during query execution.
|
||||||
}
|
/// This diagnostic will be re-emitted if we mark
|
||||||
|
/// the query as green, as that query will have the side
|
||||||
impl QuerySideEffects {
|
/// effect dep node as a dependency.
|
||||||
/// Returns true if there might be side effects.
|
Diagnostic(DiagInner),
|
||||||
#[inline]
|
|
||||||
pub fn maybe_any(&self) -> bool {
|
|
||||||
let QuerySideEffects { diagnostics } = self;
|
|
||||||
// Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped
|
|
||||||
// if `maybe_any` is known to be false.
|
|
||||||
diagnostics.has_capacity()
|
|
||||||
}
|
|
||||||
pub fn append(&mut self, other: QuerySideEffects) {
|
|
||||||
let QuerySideEffects { diagnostics } = self;
|
|
||||||
diagnostics.extend(other.diagnostics);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QueryContext: HasDepContext {
|
pub trait QueryContext: HasDepContext {
|
||||||
|
@ -101,29 +88,19 @@ pub trait QueryContext: HasDepContext {
|
||||||
|
|
||||||
fn collect_active_jobs(self) -> QueryMap;
|
fn collect_active_jobs(self) -> QueryMap;
|
||||||
|
|
||||||
/// Load side effects associated to the node in the previous session.
|
/// Load a side effect associated to the node in the previous session.
|
||||||
fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
|
fn load_side_effect(
|
||||||
|
|
||||||
/// Register diagnostics for the given node, for use in next session.
|
|
||||||
fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
|
|
||||||
|
|
||||||
/// Register diagnostics for the given node, for use in next session.
|
|
||||||
fn store_side_effects_for_anon_node(
|
|
||||||
self,
|
self,
|
||||||
dep_node_index: DepNodeIndex,
|
prev_dep_node_index: SerializedDepNodeIndex,
|
||||||
side_effects: QuerySideEffects,
|
) -> Option<QuerySideEffect>;
|
||||||
);
|
|
||||||
|
/// Register a side effect for the given node, for use in next session.
|
||||||
|
fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect);
|
||||||
|
|
||||||
/// Executes a job by changing the `ImplicitCtxt` to point to the
|
/// Executes a job by changing the `ImplicitCtxt` to point to the
|
||||||
/// new query job while it executes. It returns the diagnostics
|
/// new query job while it executes.
|
||||||
/// captured during execution and the actual result.
|
fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R)
|
||||||
fn start_query<R>(
|
-> R;
|
||||||
self,
|
|
||||||
token: QueryJobId,
|
|
||||||
depth_limit: bool,
|
|
||||||
diagnostics: Option<&Lock<ThinVec<DiagInner>>>,
|
|
||||||
compute: impl FnOnce() -> R,
|
|
||||||
) -> R;
|
|
||||||
|
|
||||||
fn depth_limit_error(self, job: QueryJobId);
|
fn depth_limit_error(self, job: QueryJobId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,9 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sharded::Sharded;
|
use rustc_data_structures::sharded::Sharded;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_data_structures::sync::Lock;
|
|
||||||
use rustc_data_structures::{outline, sync};
|
use rustc_data_structures::{outline, sync};
|
||||||
use rustc_errors::{Diag, FatalError, StashKey};
|
use rustc_errors::{Diag, FatalError, StashKey};
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use thin_vec::ThinVec;
|
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use super::QueryConfig;
|
use super::QueryConfig;
|
||||||
|
@ -25,9 +23,7 @@ use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeP
|
||||||
use crate::ich::StableHashingContext;
|
use crate::ich::StableHashingContext;
|
||||||
use crate::query::caches::QueryCache;
|
use crate::query::caches::QueryCache;
|
||||||
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
|
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
|
||||||
use crate::query::{
|
use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex};
|
||||||
QueryContext, QueryMap, QuerySideEffects, QueryStackFrame, SerializedDepNodeIndex,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct QueryState<K> {
|
pub struct QueryState<K> {
|
||||||
active: Sharded<FxHashMap<K, QueryResult>>,
|
active: Sharded<FxHashMap<K, QueryResult>>,
|
||||||
|
@ -470,7 +466,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let prof_timer = qcx.dep_context().profiler().query_provider();
|
let prof_timer = qcx.dep_context().profiler().query_provider();
|
||||||
let result = qcx.start_query(job_id, query.depth_limit(), None, || query.compute(qcx, key));
|
let result = qcx.start_query(job_id, query.depth_limit(), || query.compute(qcx, key));
|
||||||
let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index();
|
let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index();
|
||||||
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
||||||
|
|
||||||
|
@ -507,7 +503,7 @@ where
|
||||||
|
|
||||||
// The diagnostics for this query will be promoted to the current session during
|
// The diagnostics for this query will be promoted to the current session during
|
||||||
// `try_mark_green()`, so we can ignore them here.
|
// `try_mark_green()`, so we can ignore them here.
|
||||||
if let Some(ret) = qcx.start_query(job_id, false, None, || {
|
if let Some(ret) = qcx.start_query(job_id, false, || {
|
||||||
try_load_from_disk_and_cache_in_memory(query, dep_graph_data, qcx, &key, dep_node)
|
try_load_from_disk_and_cache_in_memory(query, dep_graph_data, qcx, &key, dep_node)
|
||||||
}) {
|
}) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -515,10 +511,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let prof_timer = qcx.dep_context().profiler().query_provider();
|
let prof_timer = qcx.dep_context().profiler().query_provider();
|
||||||
let diagnostics = Lock::new(ThinVec::new());
|
|
||||||
|
|
||||||
let (result, dep_node_index) =
|
let (result, dep_node_index) = qcx.start_query(job_id, query.depth_limit(), || {
|
||||||
qcx.start_query(job_id, query.depth_limit(), Some(&diagnostics), || {
|
|
||||||
if query.anon() {
|
if query.anon() {
|
||||||
return dep_graph_data.with_anon_task_inner(
|
return dep_graph_data.with_anon_task_inner(
|
||||||
*qcx.dep_context(),
|
*qcx.dep_context(),
|
||||||
|
@ -542,16 +536,6 @@ where
|
||||||
|
|
||||||
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
|
||||||
|
|
||||||
let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() };
|
|
||||||
|
|
||||||
if std::intrinsics::unlikely(side_effects.maybe_any()) {
|
|
||||||
if query.anon() {
|
|
||||||
qcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
|
|
||||||
} else {
|
|
||||||
qcx.store_side_effects(dep_node_index, side_effects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(result, dep_node_index)
|
(result, dep_node_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2525,7 +2525,7 @@ written to standard error output)"),
|
||||||
"for every macro invocation, print its name and arguments (default: no)"),
|
"for every macro invocation, print its name and arguments (default: no)"),
|
||||||
track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
|
track_diagnostics: bool = (false, parse_bool, [UNTRACKED],
|
||||||
"tracks where in rustc a diagnostic was emitted"),
|
"tracks where in rustc a diagnostic was emitted"),
|
||||||
// Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
|
// Diagnostics are considered side-effects of a query (see `QuerySideEffect`) and are saved
|
||||||
// alongside query results and changes to translation options can affect diagnostics - so
|
// alongside query results and changes to translation options can affect diagnostics - so
|
||||||
// translation options should be tracked.
|
// translation options should be tracked.
|
||||||
translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue