Skip to content

Commit 17bd715

Browse files
committed
Make create_def invoke a helper query if used from a recorded query
1 parent 128f38d commit 17bd715

File tree

8 files changed

+131
-32
lines changed

8 files changed

+131
-32
lines changed

compiler/rustc_hir/src/definitions.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use std::hash::Hash;
1010
use rustc_data_structures::stable_hasher::StableHasher;
1111
use rustc_data_structures::unord::UnordMap;
1212
use rustc_hashes::Hash64;
13-
use rustc_index::IndexVec;
14-
use rustc_macros::{Decodable, Encodable};
13+
use rustc_index::{IndexVec, static_assert_size};
14+
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
1515
use rustc_span::{Symbol, kw, sym};
1616
use tracing::{debug, instrument};
1717

@@ -252,7 +252,7 @@ impl DefPath {
252252
}
253253

254254
/// New variants should only be added in synchronization with `enum DefKind`.
255-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
255+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
256256
pub enum DefPathData {
257257
// Root: these should only be used for the root nodes, because
258258
// they are treated specially by the `def_path` function.
@@ -293,6 +293,8 @@ pub enum DefPathData {
293293
SyntheticCoroutineBody,
294294
}
295295

296+
static_assert_size!(DefPathData, 8);
297+
296298
impl Definitions {
297299
pub fn def_path_table(&self) -> &DefPathTable {
298300
&self.table
@@ -346,7 +348,12 @@ impl Definitions {
346348
}
347349

348350
/// Adds a definition with a parent definition.
349-
pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId {
351+
pub fn create_def(
352+
&mut self,
353+
parent: LocalDefId,
354+
data: DefPathData,
355+
query_local_disambiguator: Option<u32>,
356+
) -> LocalDefId {
350357
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
351358
// reference to `Definitions` and we're already holding a mutable reference.
352359
debug!(
@@ -361,8 +368,20 @@ impl Definitions {
361368
let disambiguator = {
362369
let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0);
363370
let disambiguator = *next_disamb;
364-
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
365-
disambiguator
371+
// The disambiguator number space is split into the ones counting from 0 upwards,
372+
match query_local_disambiguator {
373+
None => {
374+
assert!(disambiguator < u32::MAX / 2);
375+
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
376+
disambiguator
377+
}
378+
// and the ones counting from MAX downwards.
379+
Some(local) => {
380+
// Ensure these two number spaces do not collide. 2^31 disambiguators should be enough for everyone.
381+
assert!(local < u32::MAX / 2);
382+
u32::MAX - local
383+
}
384+
}
366385
};
367386
let key = DefKey {
368387
parent: Some(parent.local_def_index),

compiler/rustc_interface/src/callbacks.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
2525
// Skip doing anything if we aren't tracking dependencies.
2626
let tracks_deps = match icx.task_deps {
2727
TaskDepsRef::Allow(..) => true,
28-
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore | TaskDepsRef::Forbid => false,
28+
TaskDepsRef::Replay { .. }
29+
| TaskDepsRef::EvalAlways
30+
| TaskDepsRef::Ignore
31+
| TaskDepsRef::Forbid => false,
2932
};
3033
if tracks_deps {
3134
let _span = icx.tcx.source_span(def_id);

compiler/rustc_middle/src/hir/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,11 @@ pub fn provide(providers: &mut Providers) {
239239
providers.in_scope_traits_map = |tcx, id| {
240240
tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map)
241241
};
242+
providers.create_def_raw = |tcx, (parent, data, query_local_disambiguator)| {
243+
tcx.untracked().definitions.write().create_def(
244+
parent,
245+
data,
246+
Some(query_local_disambiguator),
247+
)
248+
}
242249
}

compiler/rustc_middle/src/query/keys.rs

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::ffi::OsStr;
44

55
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
6+
use rustc_hir::definitions::DefPathData;
67
use rustc_hir::hir_id::{HirId, OwnerId};
78
use rustc_query_system::dep_graph::DepNodeIndex;
89
use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
@@ -265,6 +266,14 @@ impl Key for (LocalDefId, LocalDefId) {
265266
}
266267
}
267268

269+
impl Key for (LocalDefId, DefPathData, u32) {
270+
type Cache<V> = DefaultCache<Self, V>;
271+
272+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
273+
self.0.default_span(tcx)
274+
}
275+
}
276+
268277
impl Key for (DefId, Ident) {
269278
type Cache<V> = DefaultCache<Self, V>;
270279

compiler/rustc_middle/src/query/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ rustc_queries! {
159159
desc { "getting the source span" }
160160
}
161161

162+
/// Used to handle incremental replays of [`TyCtxt::create_def``] invocations from tracked queries.
163+
query create_def_raw(key: (LocalDefId, rustc_hir::definitions::DefPathData, u32)) -> LocalDefId {
164+
// Accesses untracked data
165+
eval_always
166+
desc { "generating a new def id" }
167+
}
168+
162169
/// Represents crate as a whole (as distinct from the top-level crate module).
163170
///
164171
/// If you call `tcx.hir_crate(())` we will have to assume that any change

compiler/rustc_middle/src/ty/context.rs

+37-22
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
4141
use rustc_index::IndexVec;
4242
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
4343
use rustc_query_system::cache::WithDepNode;
44-
use rustc_query_system::dep_graph::DepNodeIndex;
44+
use rustc_query_system::dep_graph::{DepNodeIndex, TaskDepsRef};
4545
use rustc_query_system::ich::StableHashingContext;
4646
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
4747
use rustc_session::config::CrateType;
@@ -1955,27 +1955,42 @@ impl<'tcx> TyCtxt<'tcx> {
19551955
def_kind: DefKind,
19561956
) -> TyCtxtFeed<'tcx, LocalDefId> {
19571957
let data = def_kind.def_path_data(name);
1958-
// The following call has the side effect of modifying the tables inside `definitions`.
1959-
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1960-
// decode the on-disk cache.
1961-
//
1962-
// Any LocalDefId which is used within queries, either as key or result, either:
1963-
// - has been created before the construction of the TyCtxt;
1964-
// - has been created by this call to `create_def`.
1965-
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1966-
// comp. engine itself.
1967-
//
1968-
// This call also writes to the value of the `source_span` query.
1969-
// This is fine because:
1970-
// - that query is `eval_always` so we won't miss its result changing;
1971-
// - this write will have happened before that query is called.
1972-
let def_id = self.untracked.definitions.write().create_def(parent, data);
1973-
1974-
// This function modifies `self.definitions` using a side-effect.
1975-
// We need to ensure that these side effects are re-run by the incr. comp. engine.
1976-
// Depending on the forever-red node will tell the graph that the calling query
1977-
// needs to be re-evaluated.
1978-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
1958+
1959+
let def_id = tls::with_context(|icx| {
1960+
match icx.task_deps {
1961+
// Always gets rerun anyway, so nothing to replay
1962+
TaskDepsRef::EvalAlways |
1963+
// Top-level queries like the resolver get rerun every time anyway
1964+
TaskDepsRef::Ignore => {
1965+
// The following call has the side effect of modifying the tables inside `definitions`.
1966+
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1967+
// decode the on-disk cache.
1968+
//
1969+
// Any LocalDefId which is used within queries, either as key or result, either:
1970+
// - has been created before the construction of the TyCtxt;
1971+
// - has been created by this call to `create_def`.
1972+
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1973+
// comp. engine itself.
1974+
//
1975+
// This call also writes to the value of the `source_span` query.
1976+
// This is fine because:
1977+
// - that query is `eval_always` so we won't miss its result changing;
1978+
// - this write will have happened before that query is called.
1979+
self.untracked.definitions.write().create_def(parent, data, None)
1980+
}
1981+
TaskDepsRef::Forbid => bug!(
1982+
"cannot create definition {parent:?} {data:?} without being able to register task dependencies"
1983+
),
1984+
TaskDepsRef::Allow(deps) => {
1985+
let idx = deps.lock().next_def_id_idx();
1986+
self.create_def_raw((parent, data, idx))
1987+
}
1988+
TaskDepsRef::Replay { created_def_ids } => {
1989+
let idx = created_def_ids.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
1990+
self.create_def_raw((parent, data, idx))
1991+
}
1992+
}
1993+
});
19791994

19801995
let feed = TyCtxtFeed { tcx: self, key: def_id };
19811996
feed.def_kind(def_kind);

compiler/rustc_query_system/src/dep_graph/graph.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ impl<D: Deps> DepGraph<D> {
207207
}
208208
}
209209

210+
pub(crate) fn with_replay<R>(&self, created_def_ids: &AtomicU32, op: impl FnOnce() -> R) -> R {
211+
D::with_deps(TaskDepsRef::Replay { created_def_ids }, op)
212+
}
213+
210214
pub fn with_ignore<OP, R>(&self, op: OP) -> R
211215
where
212216
OP: FnOnce() -> R,
@@ -361,6 +365,7 @@ impl<D: Deps> DepGraphData<D> {
361365
node: Some(key),
362366
reads: EdgesVec::new(),
363367
read_set: Default::default(),
368+
created_def_ids: 0,
364369
});
365370
(with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads)
366371
};
@@ -476,6 +481,12 @@ impl<D: Deps> DepGraph<D> {
476481
return;
477482
}
478483
TaskDepsRef::Ignore => return,
484+
// We don't need to record dependencies when rerunning a query
485+
// because we have no disk cache entry to load. The dependencies
486+
// are preserved.
487+
// FIXME: assert that the dependencies don't change instead of
488+
// recording them.
489+
TaskDepsRef::Replay { .. } => return,
479490
TaskDepsRef::Forbid => {
480491
// Reading is forbidden in this context. ICE with a useful error message.
481492
panic_on_forbidden_read(data, dep_node_index)
@@ -526,7 +537,9 @@ impl<D: Deps> DepGraph<D> {
526537
pub fn record_diagnostic<Qcx: QueryContext>(&self, qcx: Qcx, diagnostic: &DiagInner) {
527538
if let Some(ref data) = self.data {
528539
D::read_deps(|task_deps| match task_deps {
529-
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
540+
TaskDepsRef::EvalAlways | TaskDepsRef::Ignore | TaskDepsRef::Replay { .. } => {
541+
return;
542+
}
530543
TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => {
531544
self.read_index(data.encode_diagnostic(qcx, diagnostic));
532545
}
@@ -607,7 +620,7 @@ impl<D: Deps> DepGraph<D> {
607620
edges.push(DepNodeIndex::FOREVER_RED_NODE);
608621
}
609622
TaskDepsRef::Ignore => {}
610-
TaskDepsRef::Forbid => {
623+
TaskDepsRef::Replay { .. } | TaskDepsRef::Forbid => {
611624
panic!("Cannot summarize when dependencies are not recorded.")
612625
}
613626
});
@@ -1317,6 +1330,17 @@ pub enum TaskDepsRef<'a> {
13171330
/// to ensure that the decoding process doesn't itself
13181331
/// require the execution of any queries.
13191332
Forbid,
1333+
/// Side effects from the previous run made available to
1334+
/// queries when they are reexecuted because their result was not
1335+
/// available in the cache. Whenever the query creates a new `DefId`,
1336+
/// it is checked against the entries in `QuerySideEffects::definitions`
1337+
/// to ensure that the new `DefId`s are the same as the ones that were
1338+
/// created the last time the query was executed.
1339+
Replay {
1340+
/// Every new `DefId` created increases this counter so that we produce the same ones
1341+
/// as the original execution created.
1342+
created_def_ids: &'a AtomicU32,
1343+
},
13201344
}
13211345

13221346
#[derive(Debug)]
@@ -1325,6 +1349,8 @@ pub struct TaskDeps {
13251349
node: Option<DepNode>,
13261350
reads: EdgesVec,
13271351
read_set: FxHashSet<DepNodeIndex>,
1352+
/// Every new `DefId` created increases this counter so that they can be replayed.
1353+
created_def_ids: u32,
13281354
}
13291355

13301356
impl Default for TaskDeps {
@@ -1334,9 +1360,19 @@ impl Default for TaskDeps {
13341360
node: None,
13351361
reads: EdgesVec::new(),
13361362
read_set: FxHashSet::with_capacity_and_hasher(128, Default::default()),
1363+
created_def_ids: 0,
13371364
}
13381365
}
13391366
}
1367+
1368+
impl TaskDeps {
1369+
pub fn next_def_id_idx(&mut self) -> u32 {
1370+
let idx = self.created_def_ids;
1371+
self.created_def_ids += 1;
1372+
idx
1373+
}
1374+
}
1375+
13401376
// A data structure that stores Option<DepNodeColor> values as a contiguous
13411377
// array, using one u32 per entry.
13421378
pub(super) struct DepNodeColorMap {

compiler/rustc_query_system/src/query/plumbing.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::cell::Cell;
66
use std::fmt::Debug;
77
use std::hash::Hash;
88
use std::mem;
9+
use std::sync::atomic::AtomicU32;
910

1011
use hashbrown::hash_table::Entry;
1112
use rustc_data_structures::fingerprint::Fingerprint;
@@ -633,8 +634,10 @@ where
633634
// recompute.
634635
let prof_timer = qcx.dep_context().profiler().query_provider();
635636

637+
let created_def_ids = AtomicU32::new(0);
636638
// The dep-graph for this computation is already in-place.
637-
let result = qcx.dep_context().dep_graph().with_ignore(|| query.compute(qcx, *key));
639+
let result =
640+
qcx.dep_context().dep_graph().with_replay(&created_def_ids, || query.compute(qcx, *key));
638641

639642
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
640643

0 commit comments

Comments
 (0)