ICH: Replace old, transitive metadata hashing with direct hashing approach.
Instead of collecting all potential inputs to some metadata entry and hashing those, we directly hash the values we are storing in metadata. This is more accurate and doesn't suffer from quadratic blow-up when many entries have the same dependencies.
This commit is contained in:
parent
bc7af816f3
commit
ca2dce9b48
27 changed files with 689 additions and 341 deletions
|
|
@ -14,8 +14,9 @@ use locator;
|
|||
use schema;
|
||||
|
||||
use rustc::dep_graph::DepTrackingMapConfig;
|
||||
use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
|
||||
use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
|
||||
use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
|
||||
ExternCrate, NativeLibrary, LinkMeta,
|
||||
LinkagePreference, LoadedMacro, EncodedMetadata};
|
||||
use rustc::hir::def::{self, Def};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::session::Session;
|
||||
|
|
@ -498,7 +499,8 @@ impl CrateStore for cstore::CStore {
|
|||
fn encode_metadata<'a, 'tcx>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
link_meta: &LinkMeta,
|
||||
reachable: &NodeSet) -> Vec<u8>
|
||||
reachable: &NodeSet)
|
||||
-> EncodedMetadata
|
||||
{
|
||||
encoder::encode_metadata(tcx, self, link_meta, reachable)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ use cstore;
|
|||
use index::Index;
|
||||
use schema::*;
|
||||
|
||||
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
|
||||
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
|
||||
EncodedMetadata, EncodedMetadataHash};
|
||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::ich;
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir;
|
||||
|
|
@ -56,7 +56,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
|||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||
|
||||
pub metadata_hashes: Vec<(DefIndex, ich::Fingerprint)>,
|
||||
pub metadata_hashes: Vec<EncodedMetadataHash>,
|
||||
}
|
||||
|
||||
macro_rules! encoder_methods {
|
||||
|
|
@ -240,13 +240,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||
fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
|
||||
debug!("EntryBuilder::encode_item_variances({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
self.lazy_seq_from_slice(&tcx.item_variances(def_id))
|
||||
}
|
||||
|
||||
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
self.lazy(&tcx.item_type(def_id))
|
||||
let ty = tcx.item_type(def_id);
|
||||
debug!("EntryBuilder::encode_item_type({:?}) => {:?}", def_id, ty);
|
||||
self.lazy(&ty)
|
||||
}
|
||||
|
||||
/// Encode data for the given variant of the given ADT. The
|
||||
|
|
@ -261,6 +264,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
let def = tcx.lookup_adt_def(enum_did);
|
||||
let variant = &def.variants[index];
|
||||
let def_id = variant.did;
|
||||
debug!("EntryBuilder::encode_enum_variant_info({:?})", def_id);
|
||||
|
||||
let data = VariantData {
|
||||
ctor_kind: variant.ctor_kind,
|
||||
|
|
@ -307,6 +311,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
-> Entry<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
debug!("EntryBuilder::encode_info_for_mod({:?})", def_id);
|
||||
|
||||
let data = ModData {
|
||||
reexports: match tcx.export_map.get(&id) {
|
||||
|
|
@ -370,6 +375,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
let field = &variant.fields[field_index];
|
||||
|
||||
let def_id = field.did;
|
||||
debug!("EntryBuilder::encode_field({:?})", def_id);
|
||||
|
||||
let variant_id = tcx.hir.as_local_node_id(variant.did).unwrap();
|
||||
let variant_data = tcx.hir.expect_variant_data(variant_id);
|
||||
|
||||
|
|
@ -394,6 +401,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_struct_ctor({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
let variant = tcx.lookup_adt_def(adt_def_id).struct_variant();
|
||||
|
||||
|
|
@ -436,16 +444,19 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
|
||||
debug!("EntryBuilder::encode_generics({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
self.lazy(tcx.item_generics(def_id))
|
||||
}
|
||||
|
||||
fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
|
||||
debug!("EntryBuilder::encode_predicates({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
self.lazy(&tcx.item_predicates(def_id))
|
||||
}
|
||||
|
||||
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_info_for_trait_item({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
|
||||
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
|
|
@ -528,6 +539,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_info_for_impl_item({:?})", def_id);
|
||||
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
let ast_item = self.tcx.hir.expect_impl_item(node_id);
|
||||
let impl_item = self.tcx.associated_item(def_id);
|
||||
|
|
@ -614,11 +626,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Mir<'tcx>>> {
|
||||
debug!("EntryBuilder::encode_mir({:?})", def_id);
|
||||
self.tcx.maps.mir.borrow().get(&def_id).map(|mir| self.lazy(&*mir.borrow()))
|
||||
}
|
||||
|
||||
// Encodes the inherent implementations of a structure, enumeration, or trait.
|
||||
fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
|
||||
debug!("EntryBuilder::encode_inherent_implementations({:?})", def_id);
|
||||
match self.tcx.maps.inherent_impls.borrow().get(&def_id) {
|
||||
None => LazySeq::empty(),
|
||||
Some(implementations) => {
|
||||
|
|
@ -631,18 +645,19 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
|
||||
debug!("EntryBuilder::encode_stability({:?})", def_id);
|
||||
self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
|
||||
}
|
||||
|
||||
fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
|
||||
debug!("EntryBuilder::encode_deprecation({:?})", def_id);
|
||||
self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
|
||||
}
|
||||
|
||||
fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
debug!("encoding info for item at {}",
|
||||
tcx.sess.codemap().span_to_string(item.span));
|
||||
debug!("EntryBuilder::encode_info_for_item({:?})", def_id);
|
||||
|
||||
let kind = match item.node {
|
||||
hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
|
||||
|
|
@ -956,7 +971,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
-> Entry<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
debug!("writing foreign item {}", tcx.node_path_str(nitem.id));
|
||||
debug!("EntryBuilder::encode_info_for_foreign_item({:?})", def_id);
|
||||
|
||||
let kind = match nitem.node {
|
||||
hir::ForeignItemFn(_, ref names, _) => {
|
||||
|
|
@ -1065,6 +1080,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
fn encode_info_for_ty_param(&mut self,
|
||||
(def_id, Untracked(has_default)): (DefId, Untracked<bool>))
|
||||
-> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_info_for_ty_param({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
Entry {
|
||||
kind: EntryKind::Type,
|
||||
|
|
@ -1091,6 +1107,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_info_for_anon_ty({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
Entry {
|
||||
kind: EntryKind::Type,
|
||||
|
|
@ -1113,6 +1130,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
|
||||
debug!("EntryBuilder::encode_info_for_closure({:?})", def_id);
|
||||
let tcx = self.tcx;
|
||||
|
||||
let data = ClosureData {
|
||||
|
|
@ -1141,6 +1159,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
}
|
||||
|
||||
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
|
||||
// NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
|
||||
// we really on the HashStable specialization for [Attribute]
|
||||
// to properly filter things out.
|
||||
self.lazy_seq_from_slice(attrs)
|
||||
}
|
||||
}
|
||||
|
|
@ -1442,14 +1463,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
cstore: &cstore::CStore,
|
||||
link_meta: &LinkMeta,
|
||||
exported_symbols: &NodeSet)
|
||||
-> Vec<u8> {
|
||||
-> EncodedMetadata
|
||||
{
|
||||
let mut cursor = Cursor::new(vec![]);
|
||||
cursor.write_all(METADATA_HEADER).unwrap();
|
||||
|
||||
// Will be filed with the root position after encoding everything.
|
||||
cursor.write_all(&[0, 0, 0, 0]).unwrap();
|
||||
|
||||
let root = {
|
||||
let (root, metadata_hashes) = {
|
||||
let mut ecx = EncodeContext {
|
||||
opaque: opaque::Encoder::new(&mut cursor),
|
||||
tcx: tcx,
|
||||
|
|
@ -1467,7 +1489,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
// Encode all the entries and extra information in the crate,
|
||||
// culminating in the `CrateRoot` which points to all of it.
|
||||
ecx.encode_crate_root()
|
||||
let root = ecx.encode_crate_root();
|
||||
(root, ecx.metadata_hashes)
|
||||
};
|
||||
let mut result = cursor.into_inner();
|
||||
|
||||
|
|
@ -1479,7 +1502,10 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
result[header + 2] = (pos >> 8) as u8;
|
||||
result[header + 3] = (pos >> 0) as u8;
|
||||
|
||||
result
|
||||
EncodedMetadata {
|
||||
raw_data: result,
|
||||
hashes: metadata_hashes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
|
||||
|
|
|
|||
|
|
@ -62,16 +62,16 @@ use schema::*;
|
|||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ich::{StableHashingContext, Fingerprint};
|
||||
use rustc::middle::cstore::EncodedMetadataHash;
|
||||
use rustc::ty::TyCtxt;
|
||||
use syntax::ast;
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
||||
use rustc_serialize::Encodable;
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
|
||||
/// Builder that can encode new items, adding them into the index.
|
||||
/// Item encoding cannot be nested.
|
||||
pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
|
||||
|
|
@ -123,20 +123,36 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
|||
data: DATA)
|
||||
where DATA: DepGraphRead
|
||||
{
|
||||
let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
|
||||
data.read(self.tcx);
|
||||
|
||||
assert!(id.is_local());
|
||||
let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
|
||||
|
||||
// We don't track this since we are explicitly computing the incr. comp.
|
||||
// hashes anyway. In theory we could do some tracking here and use it to
|
||||
// avoid rehashing things (and instead cache the hashes) but it's
|
||||
// unclear whether that would be a win since hashing is cheap enough.
|
||||
let _task = tcx.dep_graph.in_ignore();
|
||||
|
||||
let compute_ich = (tcx.sess.opts.debugging_opts.query_dep_graph ||
|
||||
tcx.sess.opts.debugging_opts.incremental_cc) &&
|
||||
tcx.sess.opts.build_dep_graph();
|
||||
|
||||
let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx;
|
||||
let mut entry_builder = EntryBuilder {
|
||||
tcx: tcx,
|
||||
ecx: ecx,
|
||||
hasher: StableHasher::new(),
|
||||
hcx: StableHashingContext::new(tcx),
|
||||
hcx: if compute_ich {
|
||||
Some((StableHashingContext::new(tcx), StableHasher::new()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let entry = op(&mut entry_builder, data);
|
||||
|
||||
if let Some((ref mut hcx, ref mut hasher)) = entry_builder.hcx {
|
||||
entry.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
||||
let entry = entry_builder.ecx.lazy(&entry);
|
||||
entry_builder.finish(id);
|
||||
self.items.record(id, entry);
|
||||
|
|
@ -245,21 +261,28 @@ impl<T> DepGraphRead for FromId<T> {
|
|||
pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> {
|
||||
pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
||||
hasher: StableHasher<Fingerprint>,
|
||||
hcx: StableHashingContext<'b, 'tcx>,
|
||||
hcx: Option<(StableHashingContext<'b, 'tcx>, StableHasher<Fingerprint>)>,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||
|
||||
pub fn finish(self, def_id: DefId) {
|
||||
let hash = self.hasher.finish();
|
||||
self.ecx.metadata_hashes.push((def_id.index, hash));
|
||||
if let Some((_, hasher)) = self.hcx {
|
||||
let hash = hasher.finish();
|
||||
self.ecx.metadata_hashes.push(EncodedMetadataHash {
|
||||
def_index: def_id.index,
|
||||
hash: hash,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
|
||||
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
|
||||
{
|
||||
value.hash_stable(&mut self.hcx, &mut self.hasher);
|
||||
if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
|
||||
value.hash_stable(hcx, hasher);
|
||||
debug!("metadata-hash: {:?}", hasher);
|
||||
}
|
||||
self.ecx.lazy(value)
|
||||
}
|
||||
|
||||
|
|
@ -267,22 +290,58 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
|||
where I: IntoIterator<Item = T>,
|
||||
T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
|
||||
{
|
||||
let items: Vec<T> = iter.into_iter().collect();
|
||||
items.hash_stable(&mut self.hcx, &mut self.hasher);
|
||||
self.ecx.lazy_seq(items)
|
||||
if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
|
||||
let iter = iter.into_iter();
|
||||
let (lower_bound, upper_bound) = iter.size_hint();
|
||||
|
||||
if upper_bound == Some(lower_bound) {
|
||||
lower_bound.hash_stable(hcx, hasher);
|
||||
let mut num_items_hashed = 0;
|
||||
let ret = self.ecx.lazy_seq(iter.inspect(|item| {
|
||||
item.hash_stable(hcx, hasher);
|
||||
num_items_hashed += 1;
|
||||
}));
|
||||
|
||||
// Sometimes items in a sequence are filtered out without being
|
||||
// hashed (e.g. for &[ast::Attribute]) and this code path cannot
|
||||
// handle that correctly, so we want to make sure we didn't hit
|
||||
// it by accident.
|
||||
if lower_bound != num_items_hashed {
|
||||
bug!("Hashed a different number of items ({}) than expected ({})",
|
||||
num_items_hashed,
|
||||
lower_bound);
|
||||
}
|
||||
debug!("metadata-hash: {:?}", hasher);
|
||||
ret
|
||||
} else {
|
||||
// Collect into a vec so we know the length of the sequence
|
||||
let items: AccumulateVec<[T; 32]> = iter.collect();
|
||||
items.hash_stable(hcx, hasher);
|
||||
debug!("metadata-hash: {:?}", hasher);
|
||||
self.ecx.lazy_seq(items)
|
||||
}
|
||||
} else {
|
||||
self.ecx.lazy_seq(iter)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
|
||||
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
|
||||
{
|
||||
slice.hash_stable(&mut self.hcx, &mut self.hasher);
|
||||
if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
|
||||
slice.hash_stable(hcx, hasher);
|
||||
debug!("metadata-hash: {:?}", hasher);
|
||||
}
|
||||
self.ecx.lazy_seq_ref(slice.iter())
|
||||
}
|
||||
|
||||
pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
|
||||
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
|
||||
{
|
||||
slice.hash_stable(&mut self.hcx, &mut self.hasher);
|
||||
if let Some((ref mut hcx, ref mut hasher)) = self.hcx {
|
||||
slice.hash_stable(hcx, hasher);
|
||||
debug!("metadata-hash: {:?}", hasher);
|
||||
}
|
||||
self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use index;
|
|||
use rustc::hir;
|
||||
use rustc::hir::def::{self, CtorKind};
|
||||
use rustc::hir::def_id::{DefIndex, DefId};
|
||||
use rustc::ich::StableHashingContext;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
|
||||
use rustc::middle::lang_items;
|
||||
|
|
@ -27,6 +28,7 @@ use syntax::symbol::Symbol;
|
|||
use syntax_pos::{self, Span};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
|
||||
StableHasherResult};
|
||||
|
|
@ -107,8 +109,8 @@ impl<CTX, T> HashStable<CTX> for Lazy<T> {
|
|||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
_: &mut CTX,
|
||||
_: &mut StableHasher<W>) {
|
||||
// There's nothing to do. Whatever got encoded within this Lazy<>
|
||||
// wrapper has already been hashed.
|
||||
// There's nothing to do. Whatever got encoded within this Lazy<>
|
||||
// wrapper has already been hashed.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,8 +166,8 @@ impl<CTX, T> HashStable<CTX> for LazySeq<T> {
|
|||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
_: &mut CTX,
|
||||
_: &mut StableHasher<W>) {
|
||||
// There's nothing to do. Whatever got encoded within this Lazy<>
|
||||
// wrapper has already been hashed.
|
||||
// There's nothing to do. Whatever got encoded within this Lazy<>
|
||||
// wrapper has already been hashed.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -240,6 +242,23 @@ pub struct Entry<'tcx> {
|
|||
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct Entry<'tcx> {
|
||||
kind,
|
||||
visibility,
|
||||
span,
|
||||
attributes,
|
||||
children,
|
||||
stability,
|
||||
deprecation,
|
||||
ty,
|
||||
inherent_impls,
|
||||
variances,
|
||||
generics,
|
||||
predicates,
|
||||
ast,
|
||||
mir
|
||||
});
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub enum EntryKind<'tcx> {
|
||||
Const(u8),
|
||||
|
|
@ -267,6 +286,69 @@ pub enum EntryKind<'tcx> {
|
|||
AssociatedConst(AssociatedContainer, u8),
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for EntryKind<'tcx> {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
match *self {
|
||||
EntryKind::ImmStatic |
|
||||
EntryKind::MutStatic |
|
||||
EntryKind::ForeignImmStatic |
|
||||
EntryKind::ForeignMutStatic |
|
||||
EntryKind::ForeignMod |
|
||||
EntryKind::Field |
|
||||
EntryKind::Type => {
|
||||
// Nothing else to hash here.
|
||||
}
|
||||
EntryKind::Const(qualif) => {
|
||||
qualif.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Enum(ref repr_options) => {
|
||||
repr_options.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Variant(ref variant_data) => {
|
||||
variant_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Struct(ref variant_data, ref repr_options) |
|
||||
EntryKind::Union(ref variant_data, ref repr_options) => {
|
||||
variant_data.hash_stable(hcx, hasher);
|
||||
repr_options.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Fn(ref fn_data) |
|
||||
EntryKind::ForeignFn(ref fn_data) => {
|
||||
fn_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Mod(ref mod_data) => {
|
||||
mod_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::MacroDef(ref macro_def) => {
|
||||
macro_def.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Closure(closure_data) => {
|
||||
closure_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Trait(ref trait_data) => {
|
||||
trait_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::DefaultImpl(ref impl_data) |
|
||||
EntryKind::Impl(ref impl_data) => {
|
||||
impl_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::Method(ref method_data) => {
|
||||
method_data.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::AssociatedType(associated_container) => {
|
||||
associated_container.hash_stable(hcx, hasher);
|
||||
}
|
||||
EntryKind::AssociatedConst(associated_container, qualif) => {
|
||||
associated_container.hash_stable(hcx, hasher);
|
||||
qualif.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct ModData {
|
||||
pub reexports: LazySeq<def::Export>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue