Skip to content

Commit 02c9e73

Browse files
committed
Auto merge of rust-lang#92681 - Aaron1011:task-deps-ref, r=cjgillot
Introduce new `TaskDepsRef` enum to track allow/ignore/forbid status
2 parents 86f7f78 + f64cd87 commit 02c9e73

File tree

4 files changed

+87
-61
lines changed

4 files changed

+87
-61
lines changed

compiler/rustc_middle/src/dep_graph/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::ty::{self, TyCtxt};
22
use rustc_data_structures::profiling::SelfProfilerRef;
3-
use rustc_data_structures::sync::Lock;
43
use rustc_query_system::ich::StableHashingContext;
54
use rustc_session::Session;
65

@@ -17,6 +16,7 @@ crate use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
1716

1817
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
1918
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
19+
pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>;
2020
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
2121
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
2222
pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
@@ -45,7 +45,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
4545
write!(f, ")")
4646
}
4747

48-
fn with_deps<OP, R>(task_deps: Option<&Lock<TaskDeps>>, op: OP) -> R
48+
fn with_deps<OP, R>(task_deps: TaskDepsRef<'_>, op: OP) -> R
4949
where
5050
OP: FnOnce() -> R,
5151
{
@@ -58,7 +58,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
5858

5959
fn read_deps<OP>(op: OP)
6060
where
61-
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps>>),
61+
OP: for<'a> FnOnce(TaskDepsRef<'a>),
6262
{
6363
ty::tls::with_context_opt(|icx| {
6464
let icx = if let Some(icx) = icx { icx } else { return };

compiler/rustc_middle/src/ty/context.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1661,7 +1661,7 @@ CloneLiftImpls! { for<'tcx> { Constness, traits::WellFormedLoc, } }
16611661
pub mod tls {
16621662
use super::{ptr_eq, GlobalCtxt, TyCtxt};
16631663

1664-
use crate::dep_graph::{DepKind, TaskDeps};
1664+
use crate::dep_graph::{DepKind, TaskDepsRef};
16651665
use crate::ty::query;
16661666
use rustc_data_structures::sync::{self, Lock};
16671667
use rustc_data_structures::thin_vec::ThinVec;
@@ -1697,13 +1697,19 @@ pub mod tls {
16971697

16981698
/// The current dep graph task. This is used to add dependencies to queries
16991699
/// when executing them.
1700-
pub task_deps: Option<&'a Lock<TaskDeps>>,
1700+
pub task_deps: TaskDepsRef<'a>,
17011701
}
17021702

17031703
impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
17041704
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
17051705
let tcx = TyCtxt { gcx };
1706-
ImplicitCtxt { tcx, query: None, diagnostics: None, layout_depth: 0, task_deps: None }
1706+
ImplicitCtxt {
1707+
tcx,
1708+
query: None,
1709+
diagnostics: None,
1710+
layout_depth: 0,
1711+
task_deps: TaskDepsRef::Ignore,
1712+
}
17071713
}
17081714
}
17091715

compiler/rustc_query_system/src/dep_graph/graph.rs

+70-51
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
99
use rustc_index::vec::IndexVec;
1010
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
1111
use smallvec::{smallvec, SmallVec};
12+
use std::assert_matches::assert_matches;
1213
use std::collections::hash_map::Entry;
1314
use std::fmt::Debug;
1415
use std::hash::Hash;
@@ -165,7 +166,11 @@ impl<K: DepKind> DepGraph<K> {
165166
pub fn assert_ignored(&self) {
166167
if let Some(..) = self.data {
167168
K::read_deps(|task_deps| {
168-
assert!(task_deps.is_none(), "expected no task dependency tracking");
169+
assert_matches!(
170+
task_deps,
171+
TaskDepsRef::Ignore,
172+
"expected no task dependency tracking"
173+
);
169174
})
170175
}
171176
}
@@ -174,7 +179,7 @@ impl<K: DepKind> DepGraph<K> {
174179
where
175180
OP: FnOnce() -> R,
176181
{
177-
K::with_deps(None, op)
182+
K::with_deps(TaskDepsRef::Ignore, op)
178183
}
179184

180185
/// Used to wrap the deserialization of a query result from disk,
@@ -227,10 +232,7 @@ impl<K: DepKind> DepGraph<K> {
227232
where
228233
OP: FnOnce() -> R,
229234
{
230-
let mut deps = TaskDeps::default();
231-
deps.read_allowed = false;
232-
let deps = Lock::new(deps);
233-
K::with_deps(Some(&deps), op)
235+
K::with_deps(TaskDepsRef::Forbid, op)
234236
}
235237

236238
/// Starts a new dep-graph task. Dep-graph tasks are specified
@@ -313,10 +315,15 @@ impl<K: DepKind> DepGraph<K> {
313315
reads: SmallVec::new(),
314316
read_set: Default::default(),
315317
phantom_data: PhantomData,
316-
read_allowed: true,
317318
}))
318319
};
319-
let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
320+
321+
let task_deps_ref = match &task_deps {
322+
Some(deps) => TaskDepsRef::Allow(deps),
323+
None => TaskDepsRef::Ignore,
324+
};
325+
326+
let result = K::with_deps(task_deps_ref, || task(cx, arg));
320327
let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
321328

322329
let dcx = cx.dep_context();
@@ -369,7 +376,7 @@ impl<K: DepKind> DepGraph<K> {
369376

370377
if let Some(ref data) = self.data {
371378
let task_deps = Lock::new(TaskDeps::default());
372-
let result = K::with_deps(Some(&task_deps), op);
379+
let result = K::with_deps(TaskDepsRef::Allow(&task_deps), op);
373380
let task_deps = task_deps.into_inner();
374381
let task_deps = task_deps.reads;
375382

@@ -422,47 +429,47 @@ impl<K: DepKind> DepGraph<K> {
422429
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
423430
if let Some(ref data) = self.data {
424431
K::read_deps(|task_deps| {
425-
if let Some(task_deps) = task_deps {
426-
let mut task_deps = task_deps.lock();
427-
let task_deps = &mut *task_deps;
428-
429-
if !task_deps.read_allowed {
430-
panic!("Illegal read of: {:?}", dep_node_index);
432+
let mut task_deps = match task_deps {
433+
TaskDepsRef::Allow(deps) => deps.lock(),
434+
TaskDepsRef::Ignore => return,
435+
TaskDepsRef::Forbid => {
436+
panic!("Illegal read of: {:?}", dep_node_index)
431437
}
438+
};
439+
let task_deps = &mut *task_deps;
432440

433-
if cfg!(debug_assertions) {
434-
data.current.total_read_count.fetch_add(1, Relaxed);
435-
}
441+
if cfg!(debug_assertions) {
442+
data.current.total_read_count.fetch_add(1, Relaxed);
443+
}
436444

437-
// As long as we only have a low number of reads we can avoid doing a hash
438-
// insert and potentially allocating/reallocating the hashmap
439-
let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
440-
task_deps.reads.iter().all(|other| *other != dep_node_index)
441-
} else {
442-
task_deps.read_set.insert(dep_node_index)
443-
};
444-
if new_read {
445-
task_deps.reads.push(dep_node_index);
446-
if task_deps.reads.len() == TASK_DEPS_READS_CAP {
447-
// Fill `read_set` with what we have so far so we can use the hashset
448-
// next time
449-
task_deps.read_set.extend(task_deps.reads.iter().copied());
450-
}
445+
// As long as we only have a low number of reads we can avoid doing a hash
446+
// insert and potentially allocating/reallocating the hashmap
447+
let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
448+
task_deps.reads.iter().all(|other| *other != dep_node_index)
449+
} else {
450+
task_deps.read_set.insert(dep_node_index)
451+
};
452+
if new_read {
453+
task_deps.reads.push(dep_node_index);
454+
if task_deps.reads.len() == TASK_DEPS_READS_CAP {
455+
// Fill `read_set` with what we have so far so we can use the hashset
456+
// next time
457+
task_deps.read_set.extend(task_deps.reads.iter().copied());
458+
}
451459

452-
#[cfg(debug_assertions)]
453-
{
454-
if let Some(target) = task_deps.node {
455-
if let Some(ref forbidden_edge) = data.current.forbidden_edge {
456-
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
457-
if forbidden_edge.test(&src, &target) {
458-
panic!("forbidden edge {:?} -> {:?} created", src, target)
459-
}
460+
#[cfg(debug_assertions)]
461+
{
462+
if let Some(target) = task_deps.node {
463+
if let Some(ref forbidden_edge) = data.current.forbidden_edge {
464+
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
465+
if forbidden_edge.test(&src, &target) {
466+
panic!("forbidden edge {:?} -> {:?} created", src, target)
460467
}
461468
}
462469
}
463-
} else if cfg!(debug_assertions) {
464-
data.current.total_duplicate_read_count.fetch_add(1, Relaxed);
465470
}
471+
} else if cfg!(debug_assertions) {
472+
data.current.total_duplicate_read_count.fetch_add(1, Relaxed);
466473
}
467474
})
468475
}
@@ -1185,29 +1192,41 @@ impl<K: DepKind> CurrentDepGraph<K> {
11851192
const TASK_DEPS_READS_CAP: usize = 8;
11861193
type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>;
11871194

1188-
pub struct TaskDeps<K> {
1195+
#[derive(Debug, Clone, Copy)]
1196+
pub enum TaskDepsRef<'a, K: DepKind> {
1197+
/// New dependencies can be added to the
1198+
/// `TaskDeps`. This is used when executing a 'normal' query
1199+
/// (no `eval_always` modifier)
1200+
Allow(&'a Lock<TaskDeps<K>>),
1201+
/// New dependencies are ignored. This is used when
1202+
/// executing an `eval_always` query, since there's no
1203+
/// need to track dependencies for a query that's always
1204+
/// re-executed. This is also used for `dep_graph.with_ignore`
1205+
Ignore,
1206+
/// Any attempt to add new dependencies will cause a panic.
1207+
/// This is used when decoding a query result from disk,
1208+
/// to ensure that the decoding process doesn't itself
1209+
/// require the execution of any queries.
1210+
Forbid,
1211+
}
1212+
1213+
#[derive(Debug)]
1214+
pub struct TaskDeps<K: DepKind> {
11891215
#[cfg(debug_assertions)]
11901216
node: Option<DepNode<K>>,
11911217
reads: EdgesVec,
11921218
read_set: FxHashSet<DepNodeIndex>,
11931219
phantom_data: PhantomData<DepNode<K>>,
1194-
/// Whether or not we allow `DepGraph::read_index` to run.
1195-
/// This is normally true, except inside `with_query_deserialization`,
1196-
/// where it set to `false` to enforce that no new `DepNode` edges are
1197-
/// created. See the documentation of `with_query_deserialization` for
1198-
/// more details.
1199-
read_allowed: bool,
12001220
}
12011221

1202-
impl<K> Default for TaskDeps<K> {
1222+
impl<K: DepKind> Default for TaskDeps<K> {
12031223
fn default() -> Self {
12041224
Self {
12051225
#[cfg(debug_assertions)]
12061226
node: None,
12071227
reads: EdgesVec::new(),
12081228
read_set: FxHashSet::default(),
12091229
phantom_data: PhantomData,
1210-
read_allowed: true,
12111230
}
12121231
}
12131232
}

compiler/rustc_query_system/src/dep_graph/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ mod query;
55
mod serialized;
66

77
pub use dep_node::{DepNode, DepNodeParams, WorkProductId};
8-
pub use graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
8+
pub use graph::{
9+
hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct,
10+
};
911
pub use query::DepGraphQuery;
1012
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};
1113

1214
use crate::ich::StableHashingContext;
1315
use rustc_data_structures::profiling::SelfProfilerRef;
14-
use rustc_data_structures::sync::Lock;
1516
use rustc_serialize::{opaque::FileEncoder, Encodable};
1617
use rustc_session::Session;
1718

@@ -90,12 +91,12 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Hash + Send + Encodable<FileEncoder>
9091
fn debug_node(node: &DepNode<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result;
9192

9293
/// Execute the operation with provided dependencies.
93-
fn with_deps<OP, R>(deps: Option<&Lock<TaskDeps<Self>>>, op: OP) -> R
94+
fn with_deps<OP, R>(deps: TaskDepsRef<'_, Self>, op: OP) -> R
9495
where
9596
OP: FnOnce() -> R;
9697

9798
/// Access dependencies from current implicit context.
9899
fn read_deps<OP>(op: OP)
99100
where
100-
OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps<Self>>>);
101+
OP: for<'a> FnOnce(TaskDepsRef<'a, Self>);
101102
}

0 commit comments

Comments
 (0)