Skip to content

Commit 03e5741

Browse files
committed
Load all DefPathHash -> DefId mappings before dumping dep graph
Fixes rust-lang#79723
1 parent 417fe47 commit 03e5741

File tree

9 files changed

+101
-4
lines changed

9 files changed

+101
-4
lines changed

compiler/rustc_incremental/src/assert_dep_graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
216216
}
217217

218218
fn dump_graph(tcx: TyCtxt<'_>) {
219+
tcx.build_debug_def_path_hash_map();
219220
let path: String = env::var("RUST_DEP_GRAPH").unwrap_or_else(|_| "dep_graph".to_string());
220221
let query = tcx.dep_graph.query();
221222

compiler/rustc_incremental/src/persist/load.rs

+6
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ pub fn load_query_result_cache<'a>(
210210
definitions: &Definitions,
211211
) -> Option<OnDiskCache<'a>> {
212212
if sess.opts.incremental.is_none() {
213+
// Create a cache so that we can map any `DefPathHash`
214+
// to its `DefId` when printing the dep graph
215+
if sess.opts.debugging_opts.dump_dep_graph {
216+
return Some(OnDiskCache::new_empty(sess.source_map()));
217+
}
218+
// We have no use for a cache
213219
return None;
214220
}
215221

compiler/rustc_metadata/src/rmeta/decoder.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,29 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15911591
})
15921592
}
15931593

1594+
fn num_def_ids(&self) -> usize {
1595+
self.root.tables.def_keys.size()
1596+
}
1597+
1598+
// Only used when certain `-Z` flags are enabled - should *not* be used
1599+
// otherwise
1600+
fn debug_all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
1601+
let mut def_path_hashes = self.def_path_hash_cache.lock();
1602+
let mut def_index_to_data = |index| {
1603+
(self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
1604+
};
1605+
if let Some(data) = &self.root.proc_macro_data {
1606+
std::iter::once(CRATE_DEF_INDEX)
1607+
.chain(data.macros.decode(self))
1608+
.map(def_index_to_data)
1609+
.collect()
1610+
} else {
1611+
(0..self.num_def_ids())
1612+
.map(|index| def_index_to_data(DefIndex::from_usize(index)))
1613+
.collect()
1614+
}
1615+
}
1616+
15941617
#[inline]
15951618
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
15961619
let mut def_path_hashes = self.def_path_hash_cache.lock();
@@ -1926,10 +1949,6 @@ impl CrateMetadata {
19261949
self.root.hash
19271950
}
19281951

1929-
fn num_def_ids(&self) -> usize {
1930-
self.root.tables.def_keys.size()
1931-
}
1932-
19331952
fn local_def_id(&self, index: DefIndex) -> DefId {
19341953
DefId { krate: self.cnum, index }
19351954
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+8
Original file line numberDiff line numberDiff line change
@@ -529,4 +529,12 @@ impl CrateStore for CStore {
529529
fn allocator_kind(&self) -> Option<AllocatorKind> {
530530
self.allocator_kind()
531531
}
532+
533+
fn debug_all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
534+
self.get_crate_data(cnum).debug_all_def_path_hashes_and_def_ids()
535+
}
536+
537+
fn num_def_ids(&self, cnum: CrateNum) -> usize {
538+
self.get_crate_data(cnum).num_def_ids()
539+
}
532540
}

compiler/rustc_middle/src/middle/cstore.rs

+2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ pub trait CrateStore {
210210
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
211211
fn metadata_encoding_version(&self) -> &[u8];
212212
fn allocator_kind(&self) -> Option<AllocatorKind>;
213+
fn debug_all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
214+
fn num_def_ids(&self, cnum: CrateNum) -> usize;
213215
}
214216

215217
pub type CrateStoreDyn = dyn CrateStore + sync::Sync;

compiler/rustc_middle/src/ty/context.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,12 @@ impl<'tcx> TyCtxt<'tcx> {
13431343
self.queries.on_disk_cache.as_ref().map(|c| c.serialize(self, encoder)).unwrap_or(Ok(()))
13441344
}
13451345

1346+
pub fn build_debug_def_path_hash_map(self) {
1347+
if let Some(cache) = &self.queries.on_disk_cache {
1348+
cache.build_debug_def_path_hash_map(self);
1349+
}
1350+
}
1351+
13461352
/// If `true`, we should use the MIR-based borrowck, but also
13471353
/// fall back on the AST borrowck if the MIR-based one errors.
13481354
pub fn migrate_borrowck(self) -> bool {

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

+38
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, Finger
88
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
99
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
1010
use rustc_data_structures::thin_vec::ThinVec;
11+
use rustc_data_structures::unhash::UnhashMap;
1112
use rustc_errors::Diagnostic;
1213
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
1314
use rustc_hir::definitions::DefPathHash;
@@ -108,6 +109,19 @@ pub struct OnDiskCache<'sess> {
108109
// may no longer exist in the current compilation session, so
109110
// we use `Option<DefId>` so that we can cache a lookup failure.
110111
def_path_hash_to_def_id_cache: Lock<FxHashMap<DefPathHash, Option<DefId>>>,
112+
113+
// A map from a `DefPathHash` to its corresponding `DefId`, for all
114+
// known `DefId`s (both foreign and local). Building this map takes
115+
// a significant amount of time, so it is only initialized when
116+
// needed by certain `-Z` flags (currently `-Z dump-dep-graph`).
117+
// When this `OnceCell` is not initialized, the other fields of
118+
// this struct (e.g. `foreign_def_path_hahses`) are used to map
119+
// `DefPathHashes` to `DefId`s
120+
//
121+
// This field should *not* be used directly - the `def_path_hash_to_def_id`
122+
// function should be used to map a `DefPathHash` to its corresponding
123+
// `DefId`
124+
debug_def_path_hash_to_def_id: OnceCell<UnhashMap<DefPathHash, DefId>>,
111125
}
112126

113127
// This type is used only for serialization and deserialization.
@@ -215,6 +229,7 @@ impl<'sess> OnDiskCache<'sess> {
215229
latest_foreign_def_path_hashes: Default::default(),
216230
local_def_path_hash_to_def_id: make_local_def_path_hash_map(definitions),
217231
def_path_hash_to_def_id_cache: Default::default(),
232+
debug_def_path_hash_to_def_id: OnceCell::new(),
218233
}
219234
}
220235

@@ -237,6 +252,7 @@ impl<'sess> OnDiskCache<'sess> {
237252
latest_foreign_def_path_hashes: Default::default(),
238253
local_def_path_hash_to_def_id: Default::default(),
239254
def_path_hash_to_def_id_cache: Default::default(),
255+
debug_def_path_hash_to_def_id: OnceCell::new(),
240256
}
241257
}
242258

@@ -474,6 +490,20 @@ impl<'sess> OnDiskCache<'sess> {
474490
.insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
475491
}
476492

493+
pub fn build_debug_def_path_hash_map(&self, tcx: TyCtxt<'tcx>) {
494+
let crates = tcx.cstore.crates_untracked();
495+
496+
let capacity = tcx.definitions.def_path_table().num_def_ids()
497+
+ crates.iter().map(|cnum| tcx.cstore.num_def_ids(*cnum)).sum::<usize>();
498+
let mut map = UnhashMap::with_capacity_and_hasher(capacity, Default::default());
499+
500+
map.extend(tcx.definitions.def_path_table().all_def_path_hashes_and_def_ids(LOCAL_CRATE));
501+
for cnum in &crates {
502+
map.extend(tcx.cstore.debug_all_def_path_hashes_and_def_ids(*cnum).into_iter());
503+
}
504+
self.debug_def_path_hash_to_def_id.set(map).unwrap();
505+
}
506+
477507
/// If the given `dep_node`'s hash still exists in the current compilation,
478508
/// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
479509
///
@@ -625,6 +655,14 @@ impl<'sess> OnDiskCache<'sess> {
625655
Entry::Occupied(e) => *e.get(),
626656
Entry::Vacant(e) => {
627657
debug!("def_path_hash_to_def_id({:?})", hash);
658+
659+
if let Some(debug_map) = self.debug_def_path_hash_to_def_id.get() {
660+
if let Some(def_id) = debug_map.get(&hash).copied() {
661+
e.insert(Some(def_id));
662+
return Some(def_id);
663+
}
664+
}
665+
628666
// Check if the `DefPathHash` corresponds to a definition in the current
629667
// crate
630668
if let Some(def_id) = self.local_def_path_hash_to_def_id.get(&hash).cloned() {
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
include ../../run-make-fulldeps/tools.mk
2+
3+
# Tests that the dep graph contains printed def paths,
4+
# instead of just hashes
5+
6+
all: main.rs
7+
cp main.rs $(TMPDIR)/
8+
cd $(TMPDIR)
9+
$(RUSTC) -Z dump-dep-graph $<
10+
# Make sure that we can find a local function
11+
# (my_function) and something from a foreign crate
12+
# (compiler_builtins) in the dep graph
13+
grep my_function dep_graph.txt
14+
grep compiler_builtins dep_graph.txt
15+
rm dep_graph.txt dep_graph.dot
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fn my_function() {}
2+
fn main() {}

0 commit comments

Comments
 (0)