Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1aeb99d

Browse files
committedMar 19, 2025
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.
2 parents a7fc463 + b43a297 commit 1aeb99d

File tree

12 files changed

+185
-206
lines changed

12 files changed

+185
-206
lines changed
 

‎compiler/rustc_interface/src/callbacks.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::fmt;
1414
use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC};
1515
use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef};
1616
use rustc_middle::ty::tls;
17+
use rustc_query_impl::QueryCtxt;
1718
use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug;
1819
use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode};
1920

@@ -41,9 +42,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
4142
fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
4243
tls::with_context_opt(|icx| {
4344
if let Some(icx) = icx {
44-
if let Some(diagnostics) = icx.diagnostics {
45-
diagnostics.lock().extend(Some(diagnostic.clone()));
46-
}
45+
icx.tcx.dep_graph.record_diagnostic(QueryCtxt::new(icx.tcx), &diagnostic);
4746

4847
// Diagnostics are tracked, we can ignore the dependency.
4948
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };

‎compiler/rustc_middle/src/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ rustc_query_append!(define_dep_nodes![
7979
[] fn Null() -> (),
8080
/// We use this to create a forever-red node.
8181
[] fn Red() -> (),
82+
[] fn SideEffect() -> (),
8283
[] fn TraitSelect() -> (),
8384
[] fn CompileCodegenUnit() -> (),
8485
[] fn CompileMonoItem() -> (),

‎compiler/rustc_middle/src/dep_graph/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ impl Deps for DepsType {
4646

4747
const DEP_KIND_NULL: DepKind = dep_kinds::Null;
4848
const DEP_KIND_RED: DepKind = dep_kinds::Red;
49+
const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect;
4950
const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1;
5051
}
5152

‎compiler/rustc_middle/src/query/on_disk_cache.rs

+15-31
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab
1111
use rustc_hir::definitions::DefPathHash;
1212
use rustc_index::{Idx, IndexVec};
1313
use rustc_macros::{Decodable, Encodable};
14-
use rustc_query_system::query::QuerySideEffects;
14+
use rustc_query_system::query::QuerySideEffect;
1515
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
1616
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
1717
use rustc_session::Session;
@@ -55,9 +55,9 @@ pub struct OnDiskCache {
5555
// The complete cache data in serialized form.
5656
serialized_data: RwLock<Option<Mmap>>,
5757

58-
// Collects all `QuerySideEffects` created during the current compilation
58+
// Collects all `QuerySideEffect` created during the current compilation
5959
// session.
60-
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
60+
current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffect>>,
6161

6262
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
6363

@@ -68,7 +68,7 @@ pub struct OnDiskCache {
6868
// `serialized_data`.
6969
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7070

71-
// A map from dep-node to the position of any associated `QuerySideEffects` in
71+
// A map from dep-node to the position of any associated `QuerySideEffect` in
7272
// `serialized_data`.
7373
prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
7474

@@ -270,10 +270,10 @@ impl OnDiskCache {
270270
.current_side_effects
271271
.borrow()
272272
.iter()
273-
.map(|(dep_node_index, side_effects)| {
273+
.map(|(dep_node_index, side_effect)| {
274274
let pos = AbsoluteBytePos::new(encoder.position());
275275
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
276-
encoder.encode_tagged(dep_node_index, side_effects);
276+
encoder.encode_tagged(dep_node_index, side_effect);
277277

278278
(dep_node_index, pos)
279279
})
@@ -352,24 +352,23 @@ impl OnDiskCache {
352352
})
353353
}
354354

355-
/// Loads a `QuerySideEffects` created during the previous compilation session.
356-
pub fn load_side_effects(
355+
/// Loads a `QuerySideEffect` created during the previous compilation session.
356+
pub fn load_side_effect(
357357
&self,
358358
tcx: TyCtxt<'_>,
359359
dep_node_index: SerializedDepNodeIndex,
360-
) -> QuerySideEffects {
361-
let side_effects: Option<QuerySideEffects> =
360+
) -> Option<QuerySideEffect> {
361+
let side_effect: Option<QuerySideEffect> =
362362
self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
363-
364-
side_effects.unwrap_or_default()
363+
side_effect
365364
}
366365

367-
/// Stores a `QuerySideEffects` emitted during the current compilation session.
368-
/// Anything stored like this will be available via `load_side_effects` in
366+
/// Stores a `QuerySideEffect` emitted during the current compilation session.
367+
/// Anything stored like this will be available via `load_side_effect` in
369368
/// the next compilation session.
370-
pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
369+
pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
371370
let mut current_side_effects = self.current_side_effects.borrow_mut();
372-
let prev = current_side_effects.insert(dep_node_index, side_effects);
371+
let prev = current_side_effects.insert(dep_node_index, side_effect);
373372
debug_assert!(prev.is_none());
374373
}
375374

@@ -395,21 +394,6 @@ impl OnDiskCache {
395394
opt_value
396395
}
397396

398-
/// Stores side effect emitted during computation of an anonymous query.
399-
/// Since many anonymous queries can share the same `DepNode`, we aggregate
400-
/// them -- as opposed to regular queries where we assume that there is a
401-
/// 1:1 relationship between query-key and `DepNode`.
402-
pub fn store_side_effects_for_anon_node(
403-
&self,
404-
dep_node_index: DepNodeIndex,
405-
side_effects: QuerySideEffects,
406-
) {
407-
let mut current_side_effects = self.current_side_effects.borrow_mut();
408-
409-
let x = current_side_effects.entry(dep_node_index).or_default();
410-
x.append(side_effects);
411-
}
412-
413397
fn load_indexed<'tcx, T>(
414398
&self,
415399
tcx: TyCtxt<'tcx>,

‎compiler/rustc_middle/src/ty/context/tls.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::{mem, ptr};
22

3-
use rustc_data_structures::sync::{self, Lock};
4-
use rustc_errors::DiagInner;
5-
use thin_vec::ThinVec;
3+
use rustc_data_structures::sync;
64

75
use super::{GlobalCtxt, TyCtxt};
86
use crate::dep_graph::TaskDepsRef;
@@ -22,10 +20,6 @@ pub struct ImplicitCtxt<'a, 'tcx> {
2220
/// `ty::query::plumbing` when executing a query.
2321
pub query: Option<QueryJobId>,
2422

25-
/// Where to store diagnostics for the current query job, if any.
26-
/// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
27-
pub diagnostics: Option<&'a Lock<ThinVec<DiagInner>>>,
28-
2923
/// Used to prevent queries from calling too deeply.
3024
pub query_depth: usize,
3125

@@ -37,13 +31,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
3731
impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
3832
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
3933
let tcx = TyCtxt { gcx };
40-
ImplicitCtxt {
41-
tcx,
42-
query: None,
43-
diagnostics: None,
44-
query_depth: 0,
45-
task_deps: TaskDepsRef::Ignore,
46-
}
34+
ImplicitCtxt { tcx, query: None, query_depth: 0, task_deps: TaskDepsRef::Ignore }
4735
}
4836
}
4937

‎compiler/rustc_query_impl/src/plumbing.rs

+26-28
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
use std::num::NonZero;
66

77
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
8-
use rustc_data_structures::sync::Lock;
98
use rustc_data_structures::unord::UnordMap;
10-
use rustc_errors::DiagInner;
119
use rustc_hashes::Hash64;
1210
use rustc_index::Idx;
1311
use rustc_middle::bug;
@@ -26,14 +24,13 @@ use rustc_middle::ty::{self, TyCtxt};
2624
use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
2725
use rustc_query_system::ich::StableHashingContext;
2826
use rustc_query_system::query::{
29-
QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame,
27+
QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame,
3028
force_query,
3129
};
3230
use rustc_query_system::{QueryOverflow, QueryOverflowNote};
3331
use rustc_serialize::{Decodable, Encodable};
3432
use rustc_session::Limit;
3533
use rustc_span::def_id::LOCAL_CRATE;
36-
use thin_vec::ThinVec;
3734

3835
use crate::QueryConfigRestored;
3936

@@ -93,43 +90,31 @@ impl QueryContext for QueryCtxt<'_> {
9390
}
9491

9592
// Interactions with on_disk_cache
96-
fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
93+
fn load_side_effect(
94+
self,
95+
prev_dep_node_index: SerializedDepNodeIndex,
96+
) -> Option<QuerySideEffect> {
9797
self.query_system
9898
.on_disk_cache
9999
.as_ref()
100-
.map(|c| c.load_side_effects(self.tcx, prev_dep_node_index))
101-
.unwrap_or_default()
100+
.and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index))
102101
}
103102

104103
#[inline(never)]
105104
#[cold]
106-
fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
105+
fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
107106
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
108-
c.store_side_effects(dep_node_index, side_effects)
109-
}
110-
}
111-
112-
#[inline(never)]
113-
#[cold]
114-
fn store_side_effects_for_anon_node(
115-
self,
116-
dep_node_index: DepNodeIndex,
117-
side_effects: QuerySideEffects,
118-
) {
119-
if let Some(c) = self.query_system.on_disk_cache.as_ref() {
120-
c.store_side_effects_for_anon_node(dep_node_index, side_effects)
107+
c.store_side_effect(dep_node_index, side_effect)
121108
}
122109
}
123110

124111
/// Executes a job by changing the `ImplicitCtxt` to point to the
125-
/// new query job while it executes. It returns the diagnostics
126-
/// captured during execution and the actual result.
112+
/// new query job while it executes.
127113
#[inline(always)]
128114
fn start_query<R>(
129115
self,
130116
token: QueryJobId,
131117
depth_limit: bool,
132-
diagnostics: Option<&Lock<ThinVec<DiagInner>>>,
133118
compute: impl FnOnce() -> R,
134119
) -> R {
135120
// The `TyCtxt` stored in TLS has the same global interner lifetime
@@ -144,7 +129,6 @@ impl QueryContext for QueryCtxt<'_> {
144129
let new_icx = ImplicitCtxt {
145130
tcx: self.tcx,
146131
query: Some(token),
147-
diagnostics,
148132
query_depth: current_icx.query_depth + depth_limit as usize,
149133
task_deps: current_icx.task_deps,
150134
};
@@ -501,7 +485,7 @@ where
501485
is_anon,
502486
is_eval_always,
503487
fingerprint_style,
504-
force_from_dep_node: Some(|tcx, dep_node| {
488+
force_from_dep_node: Some(|tcx, dep_node, _| {
505489
force_from_dep_node(Q::config(tcx), tcx, dep_node)
506490
}),
507491
try_load_from_on_disk_cache: Some(|tcx, dep_node| {
@@ -803,7 +787,7 @@ macro_rules! define_queries {
803787
is_anon: false,
804788
is_eval_always: false,
805789
fingerprint_style: FingerprintStyle::Unit,
806-
force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
790+
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
807791
try_load_from_on_disk_cache: None,
808792
name: &"Null",
809793
}
@@ -815,12 +799,26 @@ macro_rules! define_queries {
815799
is_anon: false,
816800
is_eval_always: false,
817801
fingerprint_style: FingerprintStyle::Unit,
818-
force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)),
802+
force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)),
819803
try_load_from_on_disk_cache: None,
820804
name: &"Red",
821805
}
822806
}
823807

808+
pub(crate) fn SideEffect<'tcx>() -> DepKindStruct<'tcx> {
809+
DepKindStruct {
810+
is_anon: false,
811+
is_eval_always: false,
812+
fingerprint_style: FingerprintStyle::Unit,
813+
force_from_dep_node: Some(|tcx, _, prev_index| {
814+
tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
815+
true
816+
}),
817+
try_load_from_on_disk_cache: None,
818+
name: &"SideEffect",
819+
}
820+
}
821+
824822
pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> {
825823
DepKindStruct {
826824
is_anon: true,

‎compiler/rustc_query_system/src/dep_graph/dep_node.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd,
6464
use rustc_hir::definitions::DefPathHash;
6565
use rustc_macros::{Decodable, Encodable};
6666

67-
use super::{DepContext, FingerprintStyle};
67+
use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex};
6868
use crate::ich::StableHashingContext;
6969

7070
/// This serves as an index into arrays built by `make_dep_kind_array`.
@@ -275,7 +275,8 @@ pub struct DepKindStruct<Tcx: DepContext> {
275275
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
276276
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
277277
/// `DefId` in `tcx.def_path_hash_to_def_id`.
278-
pub force_from_dep_node: Option<fn(tcx: Tcx, dep_node: DepNode) -> bool>,
278+
pub force_from_dep_node:
279+
Option<fn(tcx: Tcx, dep_node: DepNode, prev_index: SerializedDepNodeIndex) -> bool>,
279280

280281
/// Invoke a query to put the on-disk cached value in memory.
281282
pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode)>,
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.