Split crate_hash from index_hir.

This commit is contained in:
Camille GILLOT 2021-02-28 18:58:50 +01:00
parent 553004539e
commit 323f5b2ac9
7 changed files with 99 additions and 119 deletions

View File

@ -91,7 +91,7 @@ macro_rules! arena_types {
[] predicates: rustc_middle::ty::PredicateInner<$tcx>,
// HIR query types
[few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
[few] indexed_hir: rustc_middle::hir::IndexedHir<$tcx>,
[few] hir_definitions: rustc_hir::definitions::Definitions,
[] hir_owner: rustc_middle::hir::Owner<$tcx>,
[] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,

View File

@ -2,21 +2,19 @@ use crate::arena::Arena;
use crate::hir::map::{Entry, HirOwnerData, Map};
use crate::hir::{Owner, OwnerNodes, ParentedNode};
use crate::ich::StableHashingContext;
use crate::middle::cstore::CrateStore;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::CRATE_DEF_INDEX;
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::{self, DefPathHash};
use rustc_hir::definitions;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::*;
use rustc_index::vec::{Idx, IndexVec};
use rustc_session::{CrateDisambiguator, Session};
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_span::{Span, DUMMY_SP};
use std::iter::repeat;
@ -40,10 +38,6 @@ pub(super) struct NodeCollector<'a, 'hir> {
definitions: &'a definitions::Definitions,
hcx: StableHashingContext<'a>,
// We are collecting HIR hashes here so we can compute the
// crate hash from them later on.
hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
}
fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V) {
@ -58,34 +52,13 @@ fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V
fn hash_body(
hcx: &mut StableHashingContext<'_>,
def_path_hash: DefPathHash,
item_like: impl for<'a> HashStable<StableHashingContext<'a>>,
hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
) -> Fingerprint {
let hash = {
let mut stable_hasher = StableHasher::new();
hcx.while_hashing_hir_bodies(true, |hcx| {
item_like.hash_stable(hcx, &mut stable_hasher);
});
stable_hasher.finish()
};
hir_body_nodes.push((def_path_hash, hash));
hash
}
fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
let mut upstream_crates: Vec<_> = cstore
.crates_untracked()
.iter()
.map(|&cnum| {
let name = cstore.crate_name_untracked(cnum);
let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
let hash = cstore.crate_hash_untracked(cnum);
(name, disambiguator, hash)
})
.collect();
upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
upstream_crates
let mut stable_hasher = StableHasher::new();
hcx.while_hashing_hir_bodies(true, |hcx| {
item_like.hash_stable(hcx, &mut stable_hasher);
});
stable_hasher.finish()
}
impl<'a, 'hir> NodeCollector<'a, 'hir> {
@ -96,11 +69,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
definitions: &'a definitions::Definitions,
mut hcx: StableHashingContext<'a>,
) -> NodeCollector<'a, 'hir> {
let root_mod_def_path_hash =
definitions.def_path_hash(LocalDefId { local_def_index: CRATE_DEF_INDEX });
let mut hir_body_nodes = Vec::new();
let hash = {
let Crate {
ref item,
@ -120,7 +88,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
attrs: _,
} = *krate;
hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)
hash_body(&mut hcx, item)
};
let mut collector = NodeCollector {
@ -131,7 +99,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
definitions,
hcx,
hir_body_nodes,
map: (0..definitions.def_index_count())
.map(|_| HirOwnerData { signature: None, with_bodies: None })
.collect(),
@ -147,53 +114,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
pub(super) fn finalize_and_compute_crate_hash(
mut self,
crate_disambiguator: CrateDisambiguator,
cstore: &dyn CrateStore,
commandline_args_hash: u64,
) -> (IndexVec<LocalDefId, HirOwnerData<'hir>>, Svh) {
) -> IndexVec<LocalDefId, HirOwnerData<'hir>> {
// Insert bodies into the map
for (id, body) in self.krate.bodies.iter() {
let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies;
assert!(bodies.insert(id.hir_id.local_id, body).is_none());
}
self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
let node_hashes = self.hir_body_nodes.iter().fold(
Fingerprint::ZERO,
|combined_fingerprint, &(def_path_hash, fingerprint)| {
combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
},
);
let upstream_crates = upstream_crates(cstore);
// We hash the final, remapped names of all local source files so we
// don't have to include the path prefix remapping commandline args.
// If we included the full mapping in the SVH, we could only have
// reproducible builds by compiling from the same directory. So we just
// hash the result of the mapping instead of the mapping itself.
let mut source_file_names: Vec<_> = self
.source_map
.files()
.iter()
.filter(|source_file| source_file.cnum == LOCAL_CRATE)
.map(|source_file| source_file.name_hash)
.collect();
source_file_names.sort_unstable();
let crate_hash_input = (
((node_hashes, upstream_crates), source_file_names),
(commandline_args_hash, crate_disambiguator.to_fingerprint()),
);
let mut stable_hasher = StableHasher::new();
crate_hash_input.hash_stable(&mut self.hcx, &mut stable_hasher);
let crate_hash: Fingerprint = stable_hasher.finish();
let svh = Svh::new(crate_hash.to_smaller_hash());
(self.map, svh)
self.map
}
fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) {
@ -294,10 +221,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
f: F,
) {
let prev_owner = self.current_dep_node_owner;
let def_path_hash = self.definitions.def_path_hash(dep_node_owner);
let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes);
let hash = hash_body(&mut self.hcx, item_like);
self.current_dep_node_owner = dep_node_owner;
f(self, hash);

View File

@ -1,8 +1,11 @@
use self::collector::NodeCollector;
use crate::hir::{Owner, OwnerNodes};
use crate::hir::{HirOwnerData, IndexedHir};
use crate::middle::cstore::CrateStore;
use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@ -11,7 +14,6 @@ use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::*;
use rustc_index::vec::IndexVec;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, Ident, Symbol};
@ -86,20 +88,6 @@ fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
}
}
#[derive(Debug)]
pub(super) struct HirOwnerData<'hir> {
pub(super) signature: Option<&'hir Owner<'hir>>,
pub(super) with_bodies: Option<&'hir mut OwnerNodes<'hir>>,
}
#[derive(Debug)]
pub struct IndexedHir<'hir> {
/// The SVH of the local crate.
pub crate_hash: Svh,
pub(super) map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
}
#[derive(Copy, Clone)]
pub struct Map<'hir> {
pub(super) tcx: TyCtxt<'hir>,
@ -935,19 +923,82 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe
let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map");
let (map, crate_hash) = {
let map = {
let hcx = tcx.create_stable_hashing_context();
let mut collector =
NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx);
intravisit::walk_crate(&mut collector, tcx.untracked_crate);
let crate_disambiguator = tcx.sess.local_crate_disambiguator();
let cmdline_args = tcx.sess.opts.dep_tracking_hash(true);
collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args)
collector.finalize_and_compute_crate_hash()
};
tcx.arena.alloc(IndexedHir { crate_hash, map })
tcx.arena.alloc(IndexedHir { map })
}
pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
let mut hir_body_nodes: Vec<_> = tcx
.index_hir(crate_num)
.map
.iter_enumerated()
.filter_map(|(def_id, hod)| {
let def_path_hash = tcx.definitions.def_path_hash(def_id);
let hash = hod.with_bodies.as_ref()?.hash;
Some((def_path_hash, hash))
})
.collect();
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
let node_hashes = hir_body_nodes.iter().fold(
Fingerprint::ZERO,
|combined_fingerprint, &(def_path_hash, fingerprint)| {
combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
},
);
let upstream_crates = upstream_crates(&*tcx.cstore);
// We hash the final, remapped names of all local source files so we
// don't have to include the path prefix remapping commandline args.
// If we included the full mapping in the SVH, we could only have
// reproducible builds by compiling from the same directory. So we just
// hash the result of the mapping instead of the mapping itself.
let mut source_file_names: Vec<_> = tcx
.sess
.source_map()
.files()
.iter()
.filter(|source_file| source_file.cnum == LOCAL_CRATE)
.map(|source_file| source_file.name_hash)
.collect();
source_file_names.sort_unstable();
let mut hcx = tcx.create_stable_hashing_context();
let mut stable_hasher = StableHasher::new();
node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher);
let crate_hash: Fingerprint = stable_hasher.finish();
Svh::new(crate_hash.to_smaller_hash())
}
fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
let mut upstream_crates: Vec<_> = cstore
.crates_untracked()
.iter()
.map(|&cnum| {
let name = cstore.crate_name_untracked(cnum);
let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
let hash = cstore.crate_hash_untracked(cnum);
(name, disambiguator, hash)
})
.collect();
upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
upstream_crates
}
fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {

View File

@ -19,6 +19,17 @@ use rustc_index::vec::IndexVec;
use rustc_span::DUMMY_SP;
use std::collections::BTreeMap;
#[derive(Debug)]
struct HirOwnerData<'hir> {
signature: Option<&'hir Owner<'hir>>,
with_bodies: Option<&'hir mut OwnerNodes<'hir>>,
}
#[derive(Debug)]
pub struct IndexedHir<'hir> {
map: IndexVec<LocalDefId, HirOwnerData<'hir>>,
}
#[derive(Debug)]
pub struct Owner<'tcx> {
parent: HirId,
@ -117,6 +128,7 @@ pub fn provide(providers: &mut Providers) {
};
providers.hir_crate = |tcx, _| tcx.untracked_crate;
providers.index_hir = map::index_hir;
providers.crate_hash = map::crate_hash;
providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();

View File

@ -28,7 +28,7 @@ rustc_queries! {
/// The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
/// Avoid calling this query directly.
query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> {
query index_hir(_: CrateNum) -> &'tcx crate::hir::IndexedHir<'tcx> {
eval_always
no_hash
desc { "index HIR" }

View File

@ -1,6 +1,5 @@
use crate::dep_graph;
use crate::hir::exports::Export;
use crate::hir::map;
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintLevelMap;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;

View File

@ -1,5 +1,4 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_middle::hir::map as hir_map;
@ -400,10 +399,6 @@ fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
tcx.crate_name
}
fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
tcx.index_hir(crate_num).crate_hash
}
fn instance_def_size_estimate<'tcx>(
tcx: TyCtxt<'tcx>,
instance_def: ty::InstanceDef<'tcx>,
@ -551,7 +546,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
trait_of_item,
crate_disambiguator,
original_crate_name,
crate_hash,
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,