Skip to content

Commit 2cff70b

Browse files
committed
Make create_def a query.
1 parent 90a80ee commit 2cff70b

7 files changed

Lines changed: 120 additions & 44 deletions

File tree

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::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_Generic, extension};
1515
use rustc_span::def_id::LocalDefIdMap;
1616
use rustc_span::{Symbol, kw, sym};
1717
use tracing::{debug, instrument};
@@ -277,7 +277,7 @@ impl DefPath {
277277
}
278278

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

compiler/rustc_middle/src/dep_graph/dep_node.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ use std::fmt;
5151
use std::hash::Hash;
5252

5353
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
54-
use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
54+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
5555
use rustc_hir::def_id::DefId;
5656
use rustc_hir::definitions::DefPathHash;
5757
use rustc_macros::{Decodable, Encodable, HashStable};
5858
use rustc_span::Symbol;
5959

6060
use super::{KeyFingerprintStyle, SerializedDepNodeIndex};
6161
use crate::dep_graph::DepNodeKey;
62+
use crate::ich::StableHashingContext;
6263
use crate::mono::MonoItem;
6364
use crate::ty::{TyCtxt, tls};
6465

@@ -152,6 +153,14 @@ impl fmt::Debug for DepNode {
152153
}
153154
}
154155

156+
impl HashStable<StableHashingContext<'_>> for DepNode {
157+
fn hash_stable(&self, hcx: &mut StableHashingContext<'_>, hasher: &mut StableHasher) {
158+
let DepNode { kind, key_fingerprint } = self;
159+
kind.hash_stable(hcx, hasher);
160+
Fingerprint::from(*key_fingerprint).hash_stable(hcx, hasher);
161+
}
162+
}
163+
155164
/// This struct stores function pointers and other metadata for a particular DepKind.
156165
///
157166
/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
@@ -269,7 +278,7 @@ macro_rules! define_dep_nodes {
269278
// encoding. The derived Encodable/Decodable uses leb128 encoding which is
270279
// dense when only considering this enum. But DepKind is encoded in a larger
271280
// struct, and there we can take advantage of the unused bits in the u16.
272-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
281+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, HashStable)]
273282
#[allow(non_camel_case_types)]
274283
#[repr(u16)] // Must be kept in sync with the rest of `DepKind`.
275284
pub enum DepKind {

compiler/rustc_middle/src/dep_graph/graph.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,7 @@ impl DepGraphData {
335335
let (result, edges) = if tcx.is_eval_always(dep_node.kind) {
336336
(with_deps(TaskDepsRef::EvalAlways), EdgesVec::new())
337337
} else {
338-
let task_deps = Lock::new(TaskDeps::new(
339-
#[cfg(debug_assertions)]
340-
Some(dep_node),
341-
0,
342-
));
338+
let task_deps = Lock::new(TaskDeps::new(Some(dep_node), 0));
343339
(with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads)
344340
};
345341

@@ -372,11 +368,7 @@ impl DepGraphData {
372368

373369
// Large numbers of reads are common enough here that pre-sizing `read_set`
374370
// to 128 actually helps perf on some benchmarks.
375-
let task_deps = Lock::new(TaskDeps::new(
376-
#[cfg(debug_assertions)]
377-
None,
378-
128,
379-
));
371+
let task_deps = Lock::new(TaskDeps::new(None, 128));
380372
let result = with_deps(TaskDepsRef::Allow(&task_deps), op);
381373
let task_deps = task_deps.into_inner();
382374
let reads = task_deps.reads;
@@ -486,7 +478,7 @@ impl DepGraph {
486478

487479
#[cfg(debug_assertions)]
488480
{
489-
if let Some(target) = task_deps.node
481+
if let Some(target) = task_deps.current_dep_node
490482
&& let Some(ref forbidden_edge) = data.current.forbidden_edge
491483
{
492484
let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
@@ -1220,8 +1212,10 @@ pub enum TaskDepsRef<'a> {
12201212

12211213
#[derive(Debug)]
12221214
pub struct TaskDeps {
1223-
#[cfg(debug_assertions)]
1224-
node: Option<DepNode>,
1215+
current_dep_node: Option<DepNode>,
1216+
1217+
/// Counter inside this query.
1218+
local_index: usize,
12251219

12261220
/// A vector of `DepNodeIndex`, basically.
12271221
reads: EdgesVec,
@@ -1238,16 +1232,25 @@ impl TaskDeps {
12381232
const LINEAR_SCAN_MAX: usize = 16;
12391233

12401234
#[inline]
1241-
fn new(#[cfg(debug_assertions)] node: Option<DepNode>, read_set_capacity: usize) -> Self {
1235+
fn new(current_dep_node: Option<DepNode>, read_set_capacity: usize) -> Self {
12421236
TaskDeps {
1243-
#[cfg(debug_assertions)]
1244-
node,
1237+
current_dep_node,
1238+
local_index: 0,
12451239
reads: EdgesVec::new(),
12461240
read_set: FxHashSet::with_capacity_and_hasher(read_set_capacity, Default::default()),
12471241
}
12481242
}
12491243
}
12501244

1245+
impl TaskDeps {
1246+
pub fn next_query_local_index(&mut self) -> Option<(DepNode, usize)> {
1247+
let node = self.current_dep_node?;
1248+
let index = self.local_index;
1249+
self.local_index = index + 1;
1250+
Some((node, index))
1251+
}
1252+
}
1253+
12511254
// A data structure that stores Option<DepNodeColor> values as a contiguous
12521255
// array, using one u32 per entry.
12531256
pub(super) struct DepNodeColorMap {

compiler/rustc_middle/src/queries.rs

Lines changed: 19 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::DefPathData;
7071
use rustc_hir::lang_items::{LangItem, LanguageItems};
7172
use rustc_hir::{ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate};
7273
use rustc_index::IndexVec;
@@ -82,6 +83,7 @@ use rustc_span::def_id::LOCAL_CRATE;
8283
use rustc_span::{DUMMY_SP, LocalExpnId, Span, Spanned, Symbol};
8384
use rustc_target::spec::PanicStrategy;
8485

86+
use crate::dep_graph::DepNode;
8587
use crate::hir::Crate;
8688
use crate::infer::canonical::{self, Canonical};
8789
use crate::lint::LintExpectation;
@@ -198,6 +200,23 @@ rustc_queries! {
198200
desc { "getting the source span" }
199201
}
200202

203+
/// Create a new definition.
204+
query create_def_raw(key: (
205+
LocalDefId, // parent
206+
DefPathData, // def_path_data
207+
Option<DepNode>, // caller query
208+
usize, // counter of calls to `create_def_raw` by the caller query
209+
)) -> LocalDefId {
210+
// Accesses untracked data
211+
eval_always
212+
desc {
213+
"create a new definition for `{}::{:?}`, {}th call",
214+
tcx.def_path_str(key.0),
215+
key.1,
216+
key.3,
217+
}
218+
}
219+
201220
/// Represents crate as a whole (as distinct from the top-level crate module).
202221
///
203222
/// 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: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ 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::DefPathData;
1011
use rustc_hir::hir_id::OwnerId;
1112
use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
1213

13-
use crate::dep_graph::DepNodeIndex;
14+
use crate::dep_graph::{DepNode, DepNodeIndex};
1415
use crate::ich::StableHashingContext;
1516
use crate::infer::canonical::CanonicalQueryInput;
1617
use crate::mono::CollectionMode;
@@ -361,3 +362,11 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) {
361362
self.0.default_span(tcx)
362363
}
363364
}
365+
366+
impl QueryKey for (LocalDefId, DefPathData, Option<DepNode>, usize) {
367+
type Cache<V> = DefaultCache<Self, V>;
368+
369+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
370+
DUMMY_SP
371+
}
372+
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use tracing::{debug, instrument};
5959

6060
use crate::arena::Arena;
6161
use crate::dep_graph::dep_node::make_metadata;
62-
use crate::dep_graph::{DepGraph, DepKindVTable, DepNodeIndex};
62+
use crate::dep_graph::{DepGraph, DepKindVTable, DepNode, TaskDepsRef};
6363
use crate::ich::StableHashingContext;
6464
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind};
6565
use crate::lint::emit_lint_base;
@@ -1428,6 +1428,34 @@ impl<'tcx> TyCtxt<'tcx> {
14281428
}
14291429
}
14301430

1431+
#[instrument(level = "trace", skip(tcx), ret)]
1432+
fn create_def_raw_provider<'tcx>(
1433+
tcx: TyCtxt<'tcx>,
1434+
(parent, data, query, index): (LocalDefId, DefPathData, Option<DepNode>, usize),
1435+
) -> LocalDefId {
1436+
// `query` and `index` are guaranteed to change for each successive call to
1437+
// `create_def_raw`, but in a predictable manner.
1438+
let _ = (query, index);
1439+
1440+
// This query is `eval_always`, so we can access untracked data.
1441+
let mut disambiguator_state = tcx.untracked_disambiguator_state.lock();
1442+
1443+
// The following call has the side effect of modifying the tables inside `definitions`.
1444+
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1445+
// decode the on-disk cache.
1446+
//
1447+
// Any LocalDefId which is used within queries, either as key or result, either:
1448+
// - has been created before the construction of the TyCtxt;
1449+
// - has been created by this call to `create_def`.
1450+
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1451+
// comp. engine itself.
1452+
tcx.untracked.definitions.write().create_def(
1453+
parent,
1454+
data,
1455+
disambiguator_state.get_or_create(parent),
1456+
)
1457+
}
1458+
14311459
impl<'tcx> TyCtxtAt<'tcx> {
14321460
/// Create a new definition within the incr. comp. engine.
14331461
pub fn create_def(
@@ -1437,9 +1465,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
14371465
def_kind: DefKind,
14381466
override_def_path_data: Option<DefPathData>,
14391467
) -> TyCtxtFeed<'tcx, LocalDefId> {
1440-
let feed =
1441-
self.tcx.create_def(parent, name, def_kind, override_def_path_data);
1442-
1468+
let feed = self.tcx.create_def(parent, name, def_kind, override_def_path_data);
14431469
feed.def_span(self.span);
14441470
feed
14451471
}
@@ -1455,28 +1481,36 @@ impl<'tcx> TyCtxt<'tcx> {
14551481
override_def_path_data: Option<DefPathData>,
14561482
) -> TyCtxtFeed<'tcx, LocalDefId> {
14571483
let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
1458-
let mut disambiguators = self.untracked_disambiguator_state.lock();
1459-
let disambiguator = disambiguators.get_or_create(parent);
1460-
1461-
// The following call has the side effect of modifying the tables inside `definitions`.
1462-
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
1463-
// decode the on-disk cache.
1464-
//
1465-
// Any LocalDefId which is used within queries, either as key or result, either:
1466-
// - has been created before the construction of the TyCtxt;
1467-
// - has been created by this call to `create_def`.
1468-
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
1469-
// comp. engine itself.
1470-
let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
1471-
1472-
// This function modifies `self.definitions` using a side-effect.
1473-
// We need to ensure that these side effects are re-run by the incr. comp. engine.
1474-
// Depending on the forever-red node will tell the graph that the calling query
1475-
// needs to be re-evaluated.
1476-
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
1484+
1485+
// `create_def_raw` is a query, so it can be replayed by the dep-graph engine. However, we
1486+
// may invoke it multiple times with the same `(parent, data)` pair, and we expect to
1487+
// create *different* defintions from them. In order to make this compatible with the
1488+
// general model of queries, we add additional information which must change at each call.
1489+
let (dep_node, query_local_index) = ty::tls::with_context(|icx| match icx.task_deps {
1490+
// If we are inside a query, we can only use local information, and no global
1491+
// mutable state. The current query's name and the number of calls to `create_def`
1492+
// are local to the current query, so are ok to use.
1493+
TaskDepsRef::Allow(deps) => {
1494+
let opt_dep_node_and_index = deps.lock().next_query_local_index();
1495+
if let Some((dep_node, index)) = opt_dep_node_and_index {
1496+
(Some(dep_node), index)
1497+
} else {
1498+
// No idea how to support this for now...
1499+
bug!("trying to create a definition from an anonymous query")
1500+
}
1501+
}
1502+
// If we are not tracking dependencies, we can use global mutable state,
1503+
// so we use the total number of definitions as a proxy.
1504+
TaskDepsRef::EvalAlways | TaskDepsRef::Forbid | TaskDepsRef::Ignore => {
1505+
let global_count = self.untracked.definitions.read().def_index_count();
1506+
(None, global_count)
1507+
}
1508+
});
1509+
let def_id = self.create_def_raw((parent, data, dep_node, query_local_index));
14771510

14781511
let feed = TyCtxtFeed { tcx: self, key: def_id };
14791512
feed.def_kind(def_kind);
1513+
14801514
// Unique types created for closures participate in type privacy checking.
14811515
// They have visibilities inherited from the module they are defined in.
14821516
// Visibilities for opaque types are meaningless, but still provided
@@ -2914,4 +2948,5 @@ pub fn provide(providers: &mut Providers) {
29142948
tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
29152949
};
29162950
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
2951+
providers.create_def_raw = create_def_raw_provider;
29172952
}

0 commit comments

Comments
 (0)