Skip to content

Commit 3d8ce06

Browse files
committed
Make create_def a query.
1 parent 88177f8 commit 3d8ce06

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;
@@ -632,3 +634,11 @@ impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
632634
self.0.default_span(tcx)
633635
}
634636
}
637+
638+
impl Key for (LocalDefId, DefPathData, Option<DepNode>, usize) {
639+
type Cache<V> = DefaultCache<Self, V>;
640+
641+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
642+
DUMMY_SP
643+
}
644+
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap};
2525
use rustc_hir::def_id::{
2626
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
2727
};
28+
use rustc_hir::definitions::DefPathData;
2829
use rustc_hir::lang_items::{LangItem, LanguageItems};
2930
use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
3031
use rustc_index::IndexVec;
@@ -46,6 +47,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
4647
use rustc_target::spec::PanicStrategy;
4748
use {rustc_abi as abi, rustc_ast as ast, rustc_attr_data_structures as attr, rustc_hir as hir};
4849

50+
use crate::dep_graph::DepNode;
4951
use crate::infer::canonical::{self, Canonical};
5052
use crate::lint::LintExpectation;
5153
use crate::metadata::ModChild;
@@ -159,6 +161,23 @@ rustc_queries! {
159161
desc { "getting the source span" }
160162
}
161163

164+
/// Create a new definition.
165+
query create_def_raw(key: (
166+
LocalDefId, // parent
167+
DefPathData, // def_path_data
168+
Option<DepNode>, // caller query
169+
usize, // counter of calls to `create_def_raw` by the caller query
170+
)) -> LocalDefId {
171+
// Accesses untracked data
172+
eval_always
173+
desc { |tcx|
174+
"create a new definition for `{}::{:?}`, {}th call",
175+
tcx.def_path_str(key.0),
176+
key.1,
177+
key.3,
178+
}
179+
}
180+
162181
/// Represents crate as a whole (as distinct from the top-level crate module).
163182
///
164183
/// 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
@@ -60,7 +60,7 @@ use rustc_type_ir::{
6060
use tracing::{debug, instrument};
6161

6262
use crate::arena::Arena;
63-
use crate::dep_graph::{DepGraph, DepKindStruct};
63+
use crate::dep_graph::{DepGraph, DepKindStruct, DepNode, TaskDepsRef};
6464
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, CanonicalVarKinds};
6565
use crate::lint::lint_level;
6666
use crate::metadata::ModChild;
@@ -1454,6 +1454,9 @@ pub struct GlobalCtxt<'tcx> {
14541454
pub(crate) hooks: crate::hooks::Providers,
14551455

14561456
untracked: Untracked,
1457+
/// This is shared untracked state for creating new definitions.
1458+
/// It should only be accessed by the `create_def_raw` query.
1459+
untracked_disambiguator_state: Lock<DisambiguatorState>,
14571460

14581461
pub query_system: QuerySystem<'tcx>,
14591462
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
@@ -1727,6 +1730,7 @@ impl<'tcx> TyCtxt<'tcx> {
17271730
lifetimes: common_lifetimes,
17281731
consts: common_consts,
17291732
untracked,
1733+
untracked_disambiguator_state: Lock::new(DisambiguatorState::new()),
17301734
query_system,
17311735
query_kinds,
17321736
ty_rcache: Default::default(),
@@ -2017,6 +2021,30 @@ impl<'tcx> TyCtxt<'tcx> {
20172021
}
20182022
}
20192023

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

20662101
let feed = TyCtxtFeed { tcx: self, key: def_id };
20672102
feed.def_kind(def_kind);
2103+
20682104
// Unique types created for closures participate in type privacy checking.
20692105
// They have visibilities inherited from the module they are defined in.
20702106
// Visibilities for opaque types are meaningless, but still provided
@@ -3475,6 +3511,7 @@ pub fn provide(providers: &mut Providers) {
34753511
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
34763512
};
34773513
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
3514+
providers.create_def_raw = create_def_raw_provider;
34783515
}
34793516

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

0 commit comments

Comments
 (0)