Skip to content

Load all DefPathHash -> DefId mappings before dumping dep graph #80609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_incremental/src/assert_dep_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
}

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

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_incremental/src/persist/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ pub fn load_query_result_cache<'a>(
definitions: &Definitions,
) -> Option<OnDiskCache<'a>> {
if sess.opts.incremental.is_none() {
// Create a cache so that we can map any `DefPathHash`
// to its `DefId` when printing the dep graph
if sess.opts.debugging_opts.dump_dep_graph {
return Some(OnDiskCache::new_empty(sess.source_map()));
}
// We have no use for a cache
return None;
}

Expand Down
27 changes: 23 additions & 4 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,29 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
})
}

fn num_def_ids(&self) -> usize {
self.root.tables.def_keys.size()
}

// Only used when certain `-Z` flags are enabled - should *not* be used
// otherwise
fn debug_all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
let mut def_path_hashes = self.def_path_hash_cache.lock();
let mut def_index_to_data = |index| {
(self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
};
if let Some(data) = &self.root.proc_macro_data {
std::iter::once(CRATE_DEF_INDEX)
.chain(data.macros.decode(self))
.map(def_index_to_data)
.collect()
} else {
(0..self.num_def_ids())
.map(|index| def_index_to_data(DefIndex::from_usize(index)))
.collect()
}
}

#[inline]
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
let mut def_path_hashes = self.def_path_hash_cache.lock();
Expand Down Expand Up @@ -1926,10 +1949,6 @@ impl CrateMetadata {
self.root.hash
}

fn num_def_ids(&self) -> usize {
self.root.tables.def_keys.size()
}

fn local_def_id(&self, index: DefIndex) -> DefId {
DefId { krate: self.cnum, index }
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,4 +529,12 @@ impl CrateStore for CStore {
fn allocator_kind(&self) -> Option<AllocatorKind> {
self.allocator_kind()
}

fn debug_all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
self.get_crate_data(cnum).debug_all_def_path_hashes_and_def_ids()
}

fn num_def_ids(&self, cnum: CrateNum) -> usize {
self.get_crate_data(cnum).num_def_ids()
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ pub trait CrateStore {
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
fn allocator_kind(&self) -> Option<AllocatorKind>;
fn debug_all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
fn num_def_ids(&self, cnum: CrateNum) -> usize;
}

pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,12 @@ impl<'tcx> TyCtxt<'tcx> {
self.queries.on_disk_cache.as_ref().map(|c| c.serialize(self, encoder)).unwrap_or(Ok(()))
}

pub fn build_debug_def_path_hash_map(self) {
if let Some(cache) = &self.queries.on_disk_cache {
cache.build_debug_def_path_hash_map(self);
}
}

/// If `true`, we should use the MIR-based borrowck, but also
/// fall back on the AST borrowck if the MIR-based one errors.
pub fn migrate_borrowck(self) -> bool {
Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_middle/src/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, Finger
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_data_structures::unhash::UnhashMap;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
Expand Down Expand Up @@ -108,6 +109,19 @@ pub struct OnDiskCache<'sess> {
// may no longer exist in the current compilation session, so
// we use `Option<DefId>` so that we can cache a lookup failure.
def_path_hash_to_def_id_cache: Lock<FxHashMap<DefPathHash, Option<DefId>>>,

// A map from a `DefPathHash` to its corresponding `DefId`, for all
// known `DefId`s (both foreign and local). Building this map takes
// a significant amount of time, so it is only initialized when
// needed by certain `-Z` flags (currently `-Z dump-dep-graph`).
// When this `OnceCell` is not initialized, the other fields of
// this struct (e.g. `foreign_def_path_hahses`) are used to map
// `DefPathHashes` to `DefId`s
//
// This field should *not* be used directly - the `def_path_hash_to_def_id`
// function should be used to map a `DefPathHash` to its corresponding
// `DefId`
debug_def_path_hash_to_def_id: OnceCell<UnhashMap<DefPathHash, DefId>>,
}

// This type is used only for serialization and deserialization.
Expand Down Expand Up @@ -215,6 +229,7 @@ impl<'sess> OnDiskCache<'sess> {
latest_foreign_def_path_hashes: Default::default(),
local_def_path_hash_to_def_id: make_local_def_path_hash_map(definitions),
def_path_hash_to_def_id_cache: Default::default(),
debug_def_path_hash_to_def_id: OnceCell::new(),
}
}

Expand All @@ -237,6 +252,7 @@ impl<'sess> OnDiskCache<'sess> {
latest_foreign_def_path_hashes: Default::default(),
local_def_path_hash_to_def_id: Default::default(),
def_path_hash_to_def_id_cache: Default::default(),
debug_def_path_hash_to_def_id: OnceCell::new(),
}
}

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

pub fn build_debug_def_path_hash_map(&self, tcx: TyCtxt<'tcx>) {
let crates = tcx.cstore.crates_untracked();

let capacity = tcx.definitions.def_path_table().num_def_ids()
+ crates.iter().map(|cnum| tcx.cstore.num_def_ids(*cnum)).sum::<usize>();
let mut map = UnhashMap::with_capacity_and_hasher(capacity, Default::default());

map.extend(tcx.definitions.def_path_table().all_def_path_hashes_and_def_ids(LOCAL_CRATE));
for cnum in &crates {
map.extend(tcx.cstore.debug_all_def_path_hashes_and_def_ids(*cnum).into_iter());
}
self.debug_def_path_hash_to_def_id.set(map).unwrap();
}

/// If the given `dep_node`'s hash still exists in the current compilation,
/// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
///
Expand Down Expand Up @@ -625,6 +655,14 @@ impl<'sess> OnDiskCache<'sess> {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
debug!("def_path_hash_to_def_id({:?})", hash);

if let Some(debug_map) = self.debug_def_path_hash_to_def_id.get() {
if let Some(def_id) = debug_map.get(&hash).copied() {
e.insert(Some(def_id));
return Some(def_id);
}
}

// Check if the `DefPathHash` corresponds to a definition in the current
// crate
if let Some(def_id) = self.local_def_path_hash_to_def_id.get(&hash).cloned() {
Expand Down
15 changes: 15 additions & 0 deletions src/test/run-make/dump-dep-graph/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
include ../../run-make-fulldeps/tools.mk

# Tests that the dep graph contains printed def paths,
# instead of just hashes

all: main.rs
cp main.rs $(TMPDIR)/
cd $(TMPDIR)
$(RUSTC) -Z dump-dep-graph $<
# Make sure that we can find a local function
# (my_function) and something from a foreign crate
# (compiler_builtins) in the dep graph
grep my_function dep_graph.txt
grep compiler_builtins dep_graph.txt
rm dep_graph.txt dep_graph.dot
2 changes: 2 additions & 0 deletions src/test/run-make/dump-dep-graph/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fn my_function() {}
fn main() {}