Skip to content

Commit 31b00c7

Browse files
committed
Make create_def a query.
1 parent 930c5b4 commit 31b00c7

File tree

13 files changed

+150
-102
lines changed

13 files changed

+150
-102
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,11 +532,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
532532
self.tcx.hir_def_key(self.local_def_id(node_id)),
533533
);
534534

535-
let def_id = self
536-
.tcx
537-
.at(span)
538-
.create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator)
539-
.def_id();
535+
let def_id = self.tcx.at(span).create_def(parent, name, def_kind, None).def_id();
540536

541537
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
542538
self.resolver.node_id_to_def_id.insert(node_id, def_id);

compiler/rustc_const_eval/src/interpret/intern.rs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use hir::def::DefKind;
1717
use rustc_ast::Mutability;
1818
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
1919
use rustc_hir as hir;
20-
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
20+
use rustc_hir::definitions::DefPathData;
2121
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
2222
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
2323
use rustc_middle::query::TyCtxtAt;
@@ -66,7 +66,6 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
6666
ecx: &mut InterpCx<'tcx, M>,
6767
alloc_id: AllocId,
6868
mutability: Mutability,
69-
disambiguator: Option<&mut DisambiguatorState>,
7069
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
7170
trace!("intern_shallow {:?}", alloc_id);
7271
// remove allocation
@@ -89,13 +88,7 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
8988
// link the alloc id to the actual allocation
9089
let alloc = ecx.tcx.mk_const_alloc(alloc);
9190
if let Some(static_id) = ecx.machine.static_def_id() {
92-
intern_as_new_static(
93-
ecx.tcx,
94-
static_id,
95-
alloc_id,
96-
alloc,
97-
disambiguator.expect("disambiguator needed"),
98-
);
91+
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
9992
} else {
10093
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
10194
}
@@ -109,18 +102,16 @@ fn intern_as_new_static<'tcx>(
109102
static_id: LocalDefId,
110103
alloc_id: AllocId,
111104
alloc: ConstAllocation<'tcx>,
112-
disambiguator: &mut DisambiguatorState,
113105
) {
114-
// `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`.
115-
// The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
116-
// `DisambiguatorState` ensures the generated path is unique for this call as we generate
117-
// `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
106+
// `intern_const_alloc_recursive` is called once per static. The `<static_id>::{{nested}}` path
107+
// is thus unique to `intern_const_alloc_recursive`. If there are several calls to
108+
// `intern_as_new_static`, `create_def` generates a path that is unique for this call as
109+
// generate `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
118110
let feed = tcx.create_def(
119111
static_id,
120112
None,
121113
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
122114
Some(DefPathData::NestedStatic),
123-
disambiguator,
124115
);
125116
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
126117

@@ -168,8 +159,6 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
168159
intern_kind: InternKind,
169160
ret: &MPlaceTy<'tcx>,
170161
) -> Result<(), InternResult> {
171-
let mut disambiguator = DisambiguatorState::new();
172-
173162
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
174163
// that we are starting in, and all other allocations that we are encountering recursively.
175164
let (base_mutability, inner_mutability, is_static) = match intern_kind {
@@ -213,9 +202,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
213202
alloc.1.mutability = base_mutability;
214203
alloc.1.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
215204
} else {
216-
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator))
217-
.unwrap()
218-
.collect()
205+
intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().collect()
219206
};
220207
// We need to distinguish "has just been interned" from "was already in `tcx`",
221208
// so we track this in a separate set.
@@ -308,7 +295,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
308295
// okay with losing some potential for immutability here. This can anyway only affect
309296
// `static mut`.
310297
just_interned.insert(alloc_id);
311-
match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) {
298+
match intern_shallow(ecx, alloc_id, inner_mutability) {
312299
Ok(nested) => todo.extend(nested),
313300
Err(()) => {
314301
ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning");
@@ -330,9 +317,8 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>
330317
return interp_ok(());
331318
}
332319
// Move allocation to `tcx`.
333-
if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None)
334-
.map_err(|()| err_ub!(DeadLocal))?
335-
.next()
320+
if let Some(_) =
321+
intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?.next()
336322
{
337323
// We are not doing recursive interning, so we don't currently support provenance.
338324
// (If this assertion ever triggers, we should just implement a
@@ -358,7 +344,7 @@ impl<'tcx> InterpCx<'tcx, DummyMachine> {
358344
let dest = self.allocate(layout, MemoryKind::Stack)?;
359345
f(self, &dest.clone().into())?;
360346
let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance
361-
for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() {
347+
for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() {
362348
// We are not doing recursive interning, so we don't currently support provenance.
363349
// (If this assertion ever triggers, we should just implement a
364350
// proper recursive interning loop -- or just call `intern_const_alloc_recursive`.

compiler/rustc_hir/src/definitions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_data_structures::stable_hasher::StableHasher;
1111
use rustc_data_structures::unord::UnordMap;
1212
use rustc_hashes::Hash64;
1313
use rustc_index::IndexVec;
14-
use rustc_macros::{Decodable, Encodable};
14+
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
1515
use rustc_span::{Symbol, kw, sym};
1616
use tracing::{debug, instrument};
1717

@@ -274,7 +274,7 @@ impl DefPath {
274274
}
275275

276276
/// New variants should only be added in synchronization with `enum DefKind`.
277-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
277+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
278278
pub enum DefPathData {
279279
// Root: these should only be used for the root nodes, because
280280
// they are treated specially by the `def_path` function.

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_ast::visit::walk_list;
1414
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1515
use rustc_errors::ErrorGuaranteed;
1616
use rustc_hir::def::{DefKind, Res};
17-
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
17+
use rustc_hir::definitions::DefPathData;
1818
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
1919
use rustc_hir::{
2020
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
@@ -64,7 +64,6 @@ impl ResolvedArg {
6464
struct BoundVarContext<'a, 'tcx> {
6565
tcx: TyCtxt<'tcx>,
6666
rbv: &'a mut ResolveBoundVars,
67-
disambiguator: &'a mut DisambiguatorState,
6867
scope: ScopeRef<'a>,
6968
}
7069

@@ -247,12 +246,8 @@ pub(crate) fn provide(providers: &mut Providers) {
247246
#[instrument(level = "debug", skip(tcx))]
248247
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
249248
let mut rbv = ResolveBoundVars::default();
250-
let mut visitor = BoundVarContext {
251-
tcx,
252-
rbv: &mut rbv,
253-
scope: &Scope::Root { opt_parent_item: None },
254-
disambiguator: &mut DisambiguatorState::new(),
255-
};
249+
let mut visitor =
250+
BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
256251
match tcx.hir_owner_node(local_def_id) {
257252
hir::OwnerNode::Item(item) => visitor.visit_item(item),
258253
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@@ -1098,8 +1093,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
10981093
where
10991094
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
11001095
{
1101-
let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
1102-
let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
1096+
let BoundVarContext { tcx, rbv, .. } = self;
1097+
let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
11031098
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
11041099
{
11051100
let _enter = span.enter();
@@ -1472,13 +1467,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
14721467
// `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once
14731468
// per `resolve_bound_vars` query. This is the only location that creates
14741469
// `OpaqueLifetime` paths. `<opaque_def_id>::OpaqueLifetime(..)` is thus unique
1475-
// to this query and duplicates within the query are handled by `self.disambiguator`.
1470+
// to this query.
14761471
let feed = self.tcx.create_def(
14771472
opaque_def_id,
14781473
None,
14791474
DefKind::LifetimeParam,
14801475
Some(DefPathData::OpaqueLifetime(ident.name)),
1481-
&mut self.disambiguator,
14821476
);
14831477
feed.def_span(ident.span);
14841478
feed.def_ident_span(Some(ident.span));

compiler/rustc_middle/src/query/keys.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
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};
910
use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
1011

12+
use crate::dep_graph::DepNode;
1113
use crate::infer::canonical::CanonicalQueryInput;
1214
use crate::mir::mono::CollectionMode;
1315
use crate::ty::fast_reject::SimplifiedType;
@@ -640,3 +642,11 @@ impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
640642
self.0.default_span(tcx)
641643
}
642644
}
645+
646+
impl Key for (LocalDefId, DefPathData, Option<DepNode>, usize) {
647+
type Cache<V> = DefaultCache<Self, V>;
648+
649+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
650+
DUMMY_SP
651+
}
652+
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap};
8181
use rustc_hir::def_id::{
8282
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
8383
};
84+
use rustc_hir::definitions::DefPathData;
8485
use rustc_hir::lang_items::{LangItem, LanguageItems};
8586
use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
8687
use rustc_index::IndexVec;
@@ -102,6 +103,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
102103
use rustc_target::spec::PanicStrategy;
103104
use {rustc_abi as abi, rustc_ast as ast, rustc_attr_data_structures as attr, rustc_hir as hir};
104105

106+
use crate::dep_graph::DepNode;
105107
use crate::infer::canonical::{self, Canonical};
106108
use crate::lint::LintExpectation;
107109
use crate::metadata::ModChild;
@@ -215,6 +217,23 @@ rustc_queries! {
215217
desc { "getting the source span" }
216218
}
217219

220+
/// Create a new definition.
221+
query create_def_raw(key: (
222+
LocalDefId, // parent
223+
DefPathData, // def_path_data
224+
Option<DepNode>, // caller query
225+
usize, // counter of calls to `create_def_raw` by the caller query
226+
)) -> LocalDefId {
227+
// Accesses untracked data
228+
eval_always
229+
desc { |tcx|
230+
"create a new definition for `{}::{:?}`, {}th call",
231+
tcx.def_path_str(key.0),
232+
key.1,
233+
key.3,
234+
}
235+
}
236+
218237
/// Represents crate as a whole (as distinct from the top-level crate module).
219238
///
220239
/// If you call `tcx.hir_crate(())` we will have to assume that any change

compiler/rustc_middle/src/ty/context.rs

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use rustc_type_ir::{
6161
use tracing::{debug, instrument};
6262

6363
use crate::arena::Arena;
64-
use crate::dep_graph::{DepGraph, DepKindStruct};
64+
use crate::dep_graph::{DepGraph, DepKindStruct, DepNode, TaskDepsRef};
6565
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, CanonicalVarKinds};
6666
use crate::lint::lint_level;
6767
use crate::metadata::ModChild;
@@ -1457,6 +1457,9 @@ pub struct GlobalCtxt<'tcx> {
14571457
pub(crate) hooks: crate::hooks::Providers,
14581458

14591459
untracked: Untracked,
1460+
/// This is shared untracked state for creating new definitions.
1461+
/// It should only be accessed by the `create_def_raw` query.
1462+
untracked_disambiguator_state: Lock<DisambiguatorState>,
14601463

14611464
pub query_system: QuerySystem<'tcx>,
14621465
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
@@ -1731,6 +1734,7 @@ impl<'tcx> TyCtxt<'tcx> {
17311734
lifetimes: common_lifetimes,
17321735
consts: common_consts,
17331736
untracked,
1737+
untracked_disambiguator_state: Lock::new(DisambiguatorState::new()),
17341738
query_system,
17351739
query_kinds,
17361740
ty_rcache: Default::default(),
@@ -2012,6 +2016,30 @@ impl<'tcx> TyCtxt<'tcx> {
20122016
}
20132017
}
20142018

2019+
#[instrument(level = "trace", skip(tcx), ret)]
2020+
fn create_def_raw_provider<'tcx>(
2021+
tcx: TyCtxt<'tcx>,
2022+
(parent, data, query, index): (LocalDefId, DefPathData, Option<DepNode>, usize),
2023+
) -> LocalDefId {
2024+
// `query` and `index` are guaranteed to change for each successive call to
2025+
// `create_def_raw`, but in a predictable manner.
2026+
let _ = (query, index);
2027+
2028+
// This query is `eval_always`, so we can access untracked data.
2029+
let mut disambiguator_state = tcx.untracked_disambiguator_state.lock();
2030+
2031+
// The following call has the side effect of modifying the tables inside `definitions`.
2032+
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
2033+
// decode the on-disk cache.
2034+
//
2035+
// Any LocalDefId which is used within queries, either as key or result, either:
2036+
// - has been created before the construction of the TyCtxt;
2037+
// - has been created by this call to `create_def`.
2038+
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
2039+
// comp. engine itself.
2040+
tcx.untracked.definitions.write().create_def(parent, data, &mut disambiguator_state)
2041+
}
2042+
20152043
impl<'tcx> TyCtxtAt<'tcx> {
20162044
/// Create a new definition within the incr. comp. engine.
20172045
pub fn create_def(
@@ -2020,11 +2048,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
20202048
name: Option<Symbol>,
20212049
def_kind: DefKind,
20222050
override_def_path_data: Option<DefPathData>,
2023-
disambiguator: &mut DisambiguatorState,
20242051
) -> TyCtxtFeed<'tcx, LocalDefId> {
2025-
let feed =
2026-
self.tcx.create_def(parent, name, def_kind, override_def_path_data, disambiguator);
2027-
2052+
let feed = self.tcx.create_def(parent, name, def_kind, override_def_path_data);
20282053
feed.def_span(self.span);
20292054
feed
20302055
}
@@ -2038,28 +2063,39 @@ impl<'tcx> TyCtxt<'tcx> {
20382063
name: Option<Symbol>,
20392064
def_kind: DefKind,
20402065
override_def_path_data: Option<DefPathData>,
2041-
disambiguator: &mut DisambiguatorState,
20422066
) -> TyCtxtFeed<'tcx, LocalDefId> {
20432067
let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
2044-
// The following call has the side effect of modifying the tables inside `definitions`.
2045-
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
2046-
// decode the on-disk cache.
2047-
//
2048-
// Any LocalDefId which is used within queries, either as key or result, either:
2049-
// - has been created before the construction of the TyCtxt;
2050-
// - has been created by this call to `create_def`.
2051-
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
2052-
// comp. engine itself.
2053-
let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
2054-
2055-
// This function modifies `self.definitions` using a side-effect.
2056-
// We need to ensure that these side effects are re-run by the incr. comp. engine.
2057-
// Depending on the forever-red node will tell the graph that the calling query
2058-
// needs to be re-evaluated.
2059-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
2068+
2069+
// `create_def_raw` is a query, so it can be replayed by the dep-graph engine. However, we
2070+
// may invoke it multiple times with the same `(parent, data)` pair, and we expect to
2071+
// create *different* defintions from them. In order to make this compatible with the
2072+
// general model of queries, we add additional information which must change at each call.
2073+
let (dep_node, query_local_index) =
2074+
ty::tls::with_related_context(self, |icx| match icx.task_deps {
2075+
// If we are inside a query, we can only use local information, and no global
2076+
// mutable state. The current query's name and the number of calls to `create_def`
2077+
// are local to the current query, so are ok to use.
2078+
TaskDepsRef::Allow(deps) => {
2079+
let opt_dep_node_and_index = deps.lock().next_query_local_index();
2080+
if let Some((dep_node, index)) = opt_dep_node_and_index {
2081+
(Some(dep_node), index)
2082+
} else {
2083+
// No idea how to support this for now...
2084+
bug!("trying to create a definition from an anonymous query")
2085+
}
2086+
}
2087+
// If we are not tracking dependencies, we can use global mutable state,
2088+
// so we use the total number of definitions as a proxy.
2089+
TaskDepsRef::EvalAlways | TaskDepsRef::Forbid | TaskDepsRef::Ignore => {
2090+
let global_count = self.untracked.definitions.read().def_index_count();
2091+
(None, global_count)
2092+
}
2093+
});
2094+
let def_id = self.create_def_raw((parent, data, dep_node, query_local_index));
20602095

20612096
let feed = TyCtxtFeed { tcx: self, key: def_id };
20622097
feed.def_kind(def_kind);
2098+
20632099
// Unique types created for closures participate in type privacy checking.
20642100
// They have visibilities inherited from the module they are defined in.
20652101
// Visibilities for opaque types are meaningless, but still provided
@@ -3470,6 +3506,7 @@ pub fn provide(providers: &mut Providers) {
34703506
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
34713507
};
34723508
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
3509+
providers.create_def_raw = create_def_raw_provider;
34733510
}
34743511

34753512
pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {

0 commit comments

Comments
 (0)