Skip to content

Commit 20a93fc

Browse files
committed
Auto merge of #115613 - oli-obk:create_def_forever_red, r=<try>
Make create_def a side effect instead of marking the entire query as always red Before this PR: * query A creates def id D * query A is marked as depending on the always-red node, meaning it will always get re-run * in the next run of rustc: query A is not loaded from the incremental cache, but rerun After this PR: * query A creates def id D * query system registers this a side effect (just like we collect diagnostics to re-emit them without running a query) * in the next run of rustc: query A is loaded from the incremental cache and its side effect is run (thus re-creating def id D without running query A) r? `@cjgillot` TODO: * [ ] need to make feeding queries a side effect, too. At least ones that aren't written to disk. * [ ] need to re-feed the `def_span` query * [ ] many more tests
2 parents e964cca + c5f7d12 commit 20a93fc

File tree

14 files changed

+158
-53
lines changed

14 files changed

+158
-53
lines changed

compiler/rustc_hir/src/definitions.rs

+19-16
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

@@ -67,7 +67,8 @@ impl DefPathTable {
6767
// being used.
6868
//
6969
// See the documentation for DefPathHash for more information.
70-
panic!(
70+
assert_eq!(
71+
def_path1, def_path2,
7172
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
7273
Compilation cannot continue."
7374
);
@@ -114,6 +115,13 @@ impl DisambiguatorState {
114115
this.next.insert((def_id, data), index);
115116
this
116117
}
118+
119+
pub fn next(&mut self, parent: LocalDefId, data: DefPathData) -> u32 {
120+
let next_disamb = self.next.entry((parent, data)).or_insert(0);
121+
let disambiguator = *next_disamb;
122+
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
123+
disambiguator
124+
}
117125
}
118126

119127
/// The definition table containing node definitions.
@@ -207,7 +215,7 @@ impl fmt::Display for DisambiguatedDefPathData {
207215
}
208216
}
209217

210-
#[derive(Clone, Debug, Encodable, Decodable)]
218+
#[derive(Clone, Debug, Encodable, Decodable, PartialEq)]
211219
pub struct DefPath {
212220
/// The path leading from the crate root to the item.
213221
pub data: Vec<DisambiguatedDefPathData>,
@@ -274,7 +282,7 @@ impl DefPath {
274282
}
275283

276284
/// New variants should only be added in synchronization with `enum DefKind`.
277-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
285+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
278286
pub enum DefPathData {
279287
// Root: these should only be used for the root nodes, because
280288
// they are treated specially by the `def_path` function.
@@ -320,6 +328,8 @@ pub enum DefPathData {
320328
NestedStatic,
321329
}
322330

331+
static_assert_size!(DefPathData, 8);
332+
323333
impl Definitions {
324334
pub fn def_path_table(&self) -> &DefPathTable {
325335
&self.table
@@ -381,25 +391,18 @@ impl Definitions {
381391
&mut self,
382392
parent: LocalDefId,
383393
data: DefPathData,
384-
disambiguator: &mut DisambiguatorState,
385-
) -> LocalDefId {
394+
disambiguator: u32,
395+
) -> (LocalDefId, DefPathHash) {
386396
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
387397
// reference to `Definitions` and we're already holding a mutable reference.
388398
debug!(
389-
"create_def(parent={}, data={data:?})",
399+
"create_def(parent={}, data={data:?}, disambiguator: {disambiguator})",
390400
self.def_path(parent).to_string_no_crate_verbose(),
391401
);
392402

393403
// The root node must be created in `new()`.
394404
assert!(data != DefPathData::CrateRoot);
395405

396-
// Find the next free disambiguator for this key.
397-
let disambiguator = {
398-
let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
399-
let disambiguator = *next_disamb;
400-
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
401-
disambiguator
402-
};
403406
let key = DefKey {
404407
parent: Some(parent.local_def_index),
405408
disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
@@ -411,7 +414,7 @@ impl Definitions {
411414
debug!("create_def: after disambiguation, key = {:?}", key);
412415

413416
// Create the definition.
414-
LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }
417+
(LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }, def_path_hash)
415418
}
416419

417420
#[inline(always)]

compiler/rustc_interface/src/callbacks.rs

+13
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ 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_middle::util::Providers;
1718
use rustc_query_impl::QueryCtxt;
1819
use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug;
1920
use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode};
21+
use rustc_query_system::query::DefIdInfo;
2022

2123
fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
2224
tls::with_context_opt(|icx| {
@@ -113,3 +115,14 @@ pub fn setup_callbacks() {
113115
.swap(&(dep_node_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
114116
TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _));
115117
}
118+
119+
pub fn provide(providers: &mut Providers) {
120+
providers.create_def_raw = |tcx, (parent, data, disambiguator)| {
121+
let (def_id, hash) =
122+
tcx.untracked().definitions.write().create_def(parent, data, disambiguator);
123+
124+
tcx.dep_graph
125+
.record_def(QueryCtxt::new(tcx), DefIdInfo { parent, data, hash, disambiguator });
126+
def_id
127+
}
128+
}

compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
799799
rustc_lint::provide(providers);
800800
rustc_symbol_mangling::provide(providers);
801801
rustc_codegen_ssa::provide(providers);
802+
crate::callbacks::provide(providers);
802803
*providers
803804
});
804805

compiler/rustc_middle/src/dep_graph/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_data_structures::profiling::SelfProfilerRef;
22
use rustc_query_system::ich::StableHashingContext;
3+
use rustc_query_system::query::DefIdInfo;
34
use rustc_session::Session;
45

56
use crate::ty::{self, TyCtxt};
@@ -80,6 +81,11 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
8081
self.sess
8182
}
8283

84+
fn create_def(&self, &DefIdInfo { parent, data, disambiguator: index, hash }: &DefIdInfo) {
85+
let (_, h) = self.untracked().definitions.write().create_def(parent, data, index);
86+
assert_eq!(hash, h);
87+
}
88+
8389
#[inline]
8490
fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> {
8591
&self.query_kinds[dk.as_usize()]

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

+6
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ 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+
desc { "generating a new def id" }
165+
}
166+
162167
/// Represents crate as a whole (as distinct from the top-level crate module).
163168
///
164169
/// If you call `tcx.hir_crate(())` we will have to assume that any change
@@ -2054,6 +2059,7 @@ rustc_queries! {
20542059
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
20552060
separate_provide_extern
20562061
feedable
2062+
cache_on_disk_if { def_id.is_local() }
20572063
}
20582064

20592065
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {

compiler/rustc_middle/src/ty/context.rs

+22-17
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;
@@ -1992,6 +1992,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
19921992

19931993
impl<'tcx> TyCtxt<'tcx> {
19941994
/// `tcx`-dependent operations performed for every created definition.
1995+
#[instrument(level = "trace", skip(self))]
19951996
pub fn create_def(
19961997
self,
19971998
parent: LocalDefId,
@@ -2001,22 +2002,26 @@ impl<'tcx> TyCtxt<'tcx> {
20012002
disambiguator: &mut DisambiguatorState,
20022003
) -> TyCtxtFeed<'tcx, LocalDefId> {
20032004
let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
2004-
// The following call has the side effect of modifying the tables inside `definitions`.
2005-
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
2006-
// decode the on-disk cache.
2007-
//
2008-
// Any LocalDefId which is used within queries, either as key or result, either:
2009-
// - has been created before the construction of the TyCtxt;
2010-
// - has been created by this call to `create_def`.
2011-
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
2012-
// comp. engine itself.
2013-
let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
2014-
2015-
// This function modifies `self.definitions` using a side-effect.
2016-
// We need to ensure that these side effects are re-run by the incr. comp. engine.
2017-
// Depending on the forever-red node will tell the graph that the calling query
2018-
// needs to be re-evaluated.
2019-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
2005+
2006+
let def_id = tls::with_context(|icx| {
2007+
match icx.task_deps {
2008+
// Always gets rerun anyway, so nothing to replay
2009+
TaskDepsRef::EvalAlways |
2010+
// Top-level queries like the resolver get rerun every time anyway
2011+
TaskDepsRef::Ignore => {
2012+
// The following call has the side effect of modifying the tables inside `definitions`.
2013+
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
2014+
// decode the on-disk cache.
2015+
self.untracked.definitions.write().create_def(parent, data, disambiguator.next(parent, data)).0
2016+
}
2017+
TaskDepsRef::Forbid => bug!(
2018+
"cannot create definition {parent:?} {data:?} without being able to register task dependencies"
2019+
),
2020+
TaskDepsRef::Allow(_) => {
2021+
self.create_def_raw((parent, data, disambiguator.next(parent, data)))
2022+
}
2023+
}
2024+
});
20202025

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

compiler/rustc_query_impl/src/plumbing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ macro_rules! define_queries {
871871
is_eval_always: false,
872872
fingerprint_style: FingerprintStyle::Unit,
873873
force_from_dep_node: Some(|tcx, _, prev_index| {
874-
tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index);
874+
tcx.dep_graph.force_side_effect_node(QueryCtxt::new(tcx), prev_index);
875875
true
876876
}),
877877
try_load_from_on_disk_cache: None,

0 commit comments

Comments
 (0)