Skip to content

Commit f8da2ae

Browse files
committed
Make create_def a query.
1 parent 6df3efb commit f8da2ae

5 files changed

Lines changed: 92 additions & 50 deletions

File tree

compiler/rustc_hir/src/definitions.rs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashMap;
1111
use rustc_data_structures::stable_hasher::StableHasher;
1212
use rustc_hashes::Hash64;
1313
use rustc_index::IndexVec;
14-
use rustc_macros::{BlobDecodable, Decodable, Encodable, extension};
14+
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable, extension};
1515
use rustc_span::def_id::LocalDefIdMap;
1616
use rustc_span::{Symbol, kw, sym};
1717
use tracing::{debug, instrument};
@@ -114,6 +114,28 @@ impl PerParentDisambiguatorState {
114114
next: Default::default(),
115115
}
116116
}
117+
118+
/// If there are multiple definitions with the same DefPathData and the same parent, use
119+
/// `self` to differentiate them. Distinct `PerParentDisambiguatorState` instances are not
120+
/// guaranteed to generate unique disambiguators and should instead ensure that the `parent`
121+
/// and `data` pair is distinct from other instances.
122+
pub fn disambiguate(
123+
&mut self,
124+
_parent: LocalDefId,
125+
data: DefPathData,
126+
) -> DisambiguatedDefPathData {
127+
#[cfg(debug_assertions)]
128+
debug_assert_eq!(
129+
_parent,
130+
self.parent.expect("must be set"),
131+
"provided parent and parent in disambiguator must be the same"
132+
);
133+
134+
let next_disamb = self.next.entry(data).or_insert(0);
135+
let disambiguator = *next_disamb;
136+
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
137+
DisambiguatedDefPathData { disambiguator, data }
138+
}
117139
}
118140

119141
#[extension(pub trait PerParentDisambiguatorsMap)]
@@ -183,7 +205,7 @@ impl DefKey {
183205
/// between them. This introduces some artificial ordering dependency
184206
/// but means that if you have, e.g., two impls for the same type in
185207
/// the same module, they do get distinct `DefId`s.
186-
#[derive(Copy, Clone, PartialEq, Debug, Encodable, BlobDecodable)]
208+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Encodable, BlobDecodable, HashStable)]
187209
pub struct DisambiguatedDefPathData {
188210
pub data: DefPathData,
189211
pub disambiguator: u32,
@@ -277,7 +299,7 @@ impl DefPath {
277299
}
278300

279301
/// New variants should only be added in synchronization with `enum DefKind`.
280-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, BlobDecodable)]
302+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, BlobDecodable, HashStable)]
281303
pub enum DefPathData {
282304
// Root: these should only be used for the root nodes, because
283305
// they are treated specially by the `def_path` function.
@@ -384,16 +406,7 @@ impl Definitions {
384406
}
385407

386408
/// Creates a definition with a parent definition.
387-
/// If there are multiple definitions with the same DefPathData and the same parent, use
388-
/// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not
389-
/// guaranteed to generate unique disambiguators and should instead ensure that the `parent`
390-
/// and `data` pair is distinct from other instances.
391-
pub fn create_def(
392-
&mut self,
393-
parent: LocalDefId,
394-
data: DefPathData,
395-
disambiguator: &mut PerParentDisambiguatorState,
396-
) -> LocalDefId {
409+
pub fn create_def(&mut self, parent: LocalDefId, data: DisambiguatedDefPathData) -> LocalDefId {
397410
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
398411
// reference to `Definitions` and we're already holding a mutable reference.
399412
debug!(
@@ -402,26 +415,9 @@ impl Definitions {
402415
);
403416

404417
// The root node must be created in `new()`.
405-
assert!(data != DefPathData::CrateRoot);
406-
407-
// Find the next free disambiguator for this key.
408-
let disambiguator = {
409-
#[cfg(debug_assertions)]
410-
debug_assert_eq!(
411-
parent,
412-
disambiguator.parent.expect("must be set"),
413-
"provided parent and parent in disambiguator must be the same"
414-
);
418+
assert!(data.data != DefPathData::CrateRoot);
415419

416-
let next_disamb = disambiguator.next.entry(data).or_insert(0);
417-
let disambiguator = *next_disamb;
418-
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
419-
disambiguator
420-
};
421-
let key = DefKey {
422-
parent: Some(parent.local_def_index),
423-
disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
424-
};
420+
let key = DefKey { parent: Some(parent.local_def_index), disambiguated_data: data };
425421

426422
let parent_hash = self.table.def_path_hash(parent.local_def_index);
427423
let def_path_hash = key.compute_stable_hash(parent_hash);

compiler/rustc_middle/src/queries.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap};
6767
use rustc_hir::def_id::{
6868
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
6969
};
70+
use rustc_hir::definitions::DisambiguatedDefPathData;
7071
use rustc_hir::lang_items::{LangItem, LanguageItems};
7172
use rustc_hir::{ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
7273
use rustc_index::IndexVec;
@@ -198,6 +199,17 @@ rustc_queries! {
198199
desc { "getting the source span" }
199200
}
200201

202+
/// Create a new definition.
203+
///
204+
/// This query is meant to wrap a side-effect and return the resulting newly created
205+
/// definition. In incremental mode, when replaying a query, this query caches the side-effect
206+
/// to avoid performing it twice.
207+
query create_def_raw(key: (LocalDefId, DisambiguatedDefPathData)) -> LocalDefId {
208+
// Accesses untracked data
209+
eval_always
210+
desc { "create a new definition for `{}::{:?}`", tcx.def_path_str(key.0), key.1 }
211+
}
212+
201213
/// Represents crate as a whole (as distinct from the top-level crate module).
202214
///
203215
/// If you call `tcx.hir_crate(())` we will have to assume that any change

compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl_erasable_for_types_with_no_type_params! {
214214
rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
215215
rustc_hir::def::DefKind,
216216
rustc_hir::def_id::DefId,
217+
rustc_hir::def_id::LocalDefId,
217218
rustc_middle::middle::codegen_fn_attrs::SanitizerFnAttrs,
218219
rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
219220
rustc_middle::mir::ConstQualifs,

compiler/rustc_middle/src/query/keys.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::hash::Hash;
77
use rustc_ast::tokenstream::TokenStream;
88
use rustc_data_structures::stable_hasher::HashStable;
99
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
10+
use rustc_hir::definitions::DisambiguatedDefPathData;
1011
use rustc_hir::hir_id::OwnerId;
1112
use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
1213

@@ -360,3 +361,11 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) {
360361
self.0.default_span(tcx)
361362
}
362363
}
364+
365+
impl QueryKey for (LocalDefId, DisambiguatedDefPathData) {
366+
type Cache<V> = DefaultCache<Self, V>;
367+
368+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
369+
DUMMY_SP
370+
}
371+
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ use rustc_data_structures::sync::{
3232
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan};
3333
use rustc_hir::def::DefKind;
3434
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, StableCrateIdMap};
35-
use rustc_hir::definitions::{DefPathData, Definitions, PerParentDisambiguatorState};
35+
use rustc_hir::definitions::{
36+
DefPathData, Definitions, DisambiguatedDefPathData, PerParentDisambiguatorState,
37+
};
3638
use rustc_hir::intravisit::VisitorExt;
3739
use rustc_hir::lang_items::LangItem;
3840
use rustc_hir::limit::Limit;
@@ -52,7 +54,7 @@ use tracing::{debug, instrument};
5254

5355
use crate::arena::Arena;
5456
use crate::dep_graph::dep_node::make_metadata;
55-
use crate::dep_graph::{DepGraph, DepKindVTable, DepNodeIndex};
57+
use crate::dep_graph::{DepGraph, DepKindVTable, TaskDepsRef};
5658
use crate::ich::StableHashingContext;
5759
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind};
5860
use crate::lint::emit_lint_base;
@@ -1320,6 +1322,23 @@ impl<'tcx> TyCtxt<'tcx> {
13201322
}
13211323
}
13221324

1325+
#[instrument(level = "trace", skip(tcx), ret)]
1326+
fn create_def_raw_provider<'tcx>(
1327+
tcx: TyCtxt<'tcx>,
1328+
(parent, data): (LocalDefId, DisambiguatedDefPathData),
1329+
) -> LocalDefId {
1330+
// The following call has the side effect of modifying the tables inside `definitions`.
1331+
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1332+
// decode the on-disk cache.
1333+
//
1334+
// Any LocalDefId which is used within queries, either as key or result, either:
1335+
// - has been created before the construction of the TyCtxt;
1336+
// - has been created by this call to `create_def`.
1337+
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1338+
// comp. engine itself.
1339+
tcx.untracked.definitions.write().create_def(parent, data)
1340+
}
1341+
13231342
impl<'tcx> TyCtxtAt<'tcx> {
13241343
/// Create a new definition within the incr. comp. engine.
13251344
pub fn create_def(
@@ -1349,25 +1368,29 @@ impl<'tcx> TyCtxt<'tcx> {
13491368
disambiguator: &mut PerParentDisambiguatorState,
13501369
) -> TyCtxtFeed<'tcx, LocalDefId> {
13511370
let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
1352-
// The following call has the side effect of modifying the tables inside `definitions`.
1353-
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1354-
// decode the on-disk cache.
1355-
//
1356-
// Any LocalDefId which is used within queries, either as key or result, either:
1357-
// - has been created before the construction of the TyCtxt;
1358-
// - has been created by this call to `create_def`.
1359-
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1360-
// comp. engine itself.
1361-
let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
1362-
1363-
// This function modifies `self.definitions` using a side-effect.
1364-
// We need to ensure that these side effects are re-run by the incr. comp. engine.
1365-
// Depending on the forever-red node will tell the graph that the calling query
1366-
// needs to be re-evaluated.
1367-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
1371+
1372+
// Find the next free disambiguator for this key.
1373+
let data = disambiguator.disambiguate(parent, data);
1374+
1375+
let def_id = ty::tls::with_context(|icx| match icx.task_deps {
1376+
// `create_def_raw` is a query, so it can be replayed by the dep-graph engine.
1377+
// However, we may invoke it multiple times with the same `(parent, data)` pair,
1378+
// and we expect to create *different* definitions from them.
1379+
//
1380+
// In order to make this compatible with the general model of queries, we add
1381+
// additional information which must change at each call.
1382+
TaskDepsRef::Allow(..) => self.create_def_raw((parent, data)),
1383+
1384+
// If we are not tracking dependencies, we can use global mutable state.
1385+
// This is only an optimization to avoid the cost of registering the dep-node.
1386+
TaskDepsRef::EvalAlways | TaskDepsRef::Forbid | TaskDepsRef::Ignore => {
1387+
self.untracked.definitions.write().create_def(parent, data)
1388+
}
1389+
});
13681390

13691391
let feed = TyCtxtFeed { tcx: self, key: def_id };
13701392
feed.def_kind(def_kind);
1393+
13711394
// Unique types created for closures participate in type privacy checking.
13721395
// They have visibilities inherited from the module they are defined in.
13731396
// Visibilities for opaque types are meaningless, but still provided
@@ -2801,4 +2824,5 @@ pub fn provide(providers: &mut Providers) {
28012824
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
28022825
};
28032826
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
2827+
providers.create_def_raw = create_def_raw_provider;
28042828
}

0 commit comments

Comments
 (0)