ICH: Hash everything that gets encoded into crate metadata.
This commit is contained in:
parent
c008cd70f5
commit
bc7af816f3
12 changed files with 576 additions and 66 deletions
|
@ -13,8 +13,10 @@ use hir::def_id::DefId;
|
||||||
use ich::{self, CachingCodemapView};
|
use ich::{self, CachingCodemapView};
|
||||||
use session::config::DebugInfoLevel::NoDebugInfo;
|
use session::config::DebugInfoLevel::NoDebugInfo;
|
||||||
use ty;
|
use ty;
|
||||||
|
use util::nodemap::NodeMap;
|
||||||
|
|
||||||
use std::hash as std_hash;
|
use std::hash as std_hash;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
|
@ -296,3 +298,53 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>,
|
||||||
|
map: &HashMap<K, V, R>,
|
||||||
|
extract_stable_key: F)
|
||||||
|
where K: Eq + std_hash::Hash,
|
||||||
|
V: HashStable<StableHashingContext<'a, 'tcx>>,
|
||||||
|
R: std_hash::BuildHasher,
|
||||||
|
SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
|
||||||
|
F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
|
||||||
|
W: StableHasherResult,
|
||||||
|
{
|
||||||
|
let mut keys: Vec<_> = map.keys()
|
||||||
|
.map(|k| (extract_stable_key(hcx, k), k))
|
||||||
|
.collect();
|
||||||
|
keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
|
||||||
|
keys.len().hash_stable(hcx, hasher);
|
||||||
|
for (stable_key, key) in keys {
|
||||||
|
stable_key.hash_stable(hcx, hasher);
|
||||||
|
map[key].hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>,
|
||||||
|
set: &HashSet<K, R>,
|
||||||
|
extract_stable_key: F)
|
||||||
|
where K: Eq + std_hash::Hash,
|
||||||
|
R: std_hash::BuildHasher,
|
||||||
|
SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
|
||||||
|
F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
|
||||||
|
W: StableHasherResult,
|
||||||
|
{
|
||||||
|
let mut keys: Vec<_> = set.iter()
|
||||||
|
.map(|k| extract_stable_key(hcx, k))
|
||||||
|
.collect();
|
||||||
|
keys.sort_unstable();
|
||||||
|
keys.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>,
|
||||||
|
map: &NodeMap<V>)
|
||||||
|
where V: HashStable<StableHashingContext<'a, 'tcx>>,
|
||||||
|
W: StableHasherResult,
|
||||||
|
{
|
||||||
|
hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| {
|
||||||
|
hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -11,31 +11,37 @@
|
||||||
//! This module contains `HashStable` implementations for various data types
|
//! This module contains `HashStable` implementations for various data types
|
||||||
//! from rustc::ty in no particular order.
|
//! from rustc::ty in no particular order.
|
||||||
|
|
||||||
use ich::StableHashingContext;
|
use ich::{self, StableHashingContext, NodeIdHashingMode};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
||||||
StableHasherResult};
|
StableHasherResult};
|
||||||
use std::hash as std_hash;
|
use std::hash as std_hash;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use ty;
|
use ty;
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
|
||||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
|
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'a, 'tcx>,
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
hasher: &mut StableHasher<W>) {
|
hasher: &mut StableHasher<W>) {
|
||||||
let type_hash = hcx.tcx().type_id_hash(*self);
|
let ty::TyS {
|
||||||
type_hash.hash_stable(hcx, hasher);
|
ref sty,
|
||||||
|
|
||||||
|
// The other fields just provide fast access to information that is
|
||||||
|
// also contained in `sty`, so no need to hash them.
|
||||||
|
..
|
||||||
|
} = *self;
|
||||||
|
|
||||||
|
sty.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
|
impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
|
||||||
|
|
||||||
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
|
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for &'tcx ty::Slice<T>
|
||||||
where T: HashStable<StableHashingContext<'a, 'tcx>> {
|
where T: HashStable<StableHashingContext<'a, 'tcx>> {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'a, 'tcx>,
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
hasher: &mut StableHasher<W>) {
|
hasher: &mut StableHasher<W>) {
|
||||||
(&**self).hash_stable(hcx, hasher);
|
(&self[..]).hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,9 +73,13 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Region {
|
||||||
index.hash_stable(hcx, hasher);
|
index.hash_stable(hcx, hasher);
|
||||||
name.hash_stable(hcx, hasher);
|
name.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
|
ty::ReScope(code_extent) => {
|
||||||
|
code_extent.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ty::ReFree(ref free_region) => {
|
||||||
|
free_region.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
ty::ReLateBound(..) |
|
ty::ReLateBound(..) |
|
||||||
ty::ReFree(..) |
|
|
||||||
ty::ReScope(..) |
|
|
||||||
ty::ReVar(..) |
|
ty::ReVar(..) |
|
||||||
ty::ReSkolemized(..) => {
|
ty::ReSkolemized(..) => {
|
||||||
bug!("TypeIdHasher: unexpected region {:?}", *self)
|
bug!("TypeIdHasher: unexpected region {:?}", *self)
|
||||||
|
@ -127,7 +137,6 @@ impl_stable_hash_for!(enum ty::BorrowKind {
|
||||||
MutBorrow
|
MutBorrow
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'a, 'tcx>,
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
@ -223,7 +232,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Predicate<'tcx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
_: &mut StableHashingContext<'a, 'tcx>,
|
_: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
@ -303,7 +311,6 @@ for ::middle::const_val::ConstVal<'tcx> {
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
||||||
|
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
|
impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
|
||||||
parent,
|
parent,
|
||||||
predicates
|
predicates
|
||||||
|
@ -413,3 +420,263 @@ impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
|
||||||
impl_stable_hash_for!(struct ty::DebruijnIndex {
|
impl_stable_hash_for!(struct ty::DebruijnIndex {
|
||||||
depth
|
depth
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(enum ty::cast::CastKind {
|
||||||
|
CoercionCast,
|
||||||
|
PtrPtrCast,
|
||||||
|
PtrAddrCast,
|
||||||
|
AddrPtrCast,
|
||||||
|
NumericCast,
|
||||||
|
EnumCast,
|
||||||
|
PrimIntCast,
|
||||||
|
U8CharCast,
|
||||||
|
ArrayPtrCast,
|
||||||
|
FnPtrPtrCast,
|
||||||
|
FnPtrAddrCast
|
||||||
|
});
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
|
||||||
|
{
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||||
|
hcx.tcx().region_maps.code_extent_data(*self).hash_stable(hcx, hasher);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
|
||||||
|
{
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
use middle::region::CodeExtentData;
|
||||||
|
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
match *self {
|
||||||
|
CodeExtentData::Misc(node_id) |
|
||||||
|
CodeExtentData::DestructionScope(node_id) => {
|
||||||
|
node_id.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
CodeExtentData::CallSiteScope { fn_id, body_id } |
|
||||||
|
CodeExtentData::ParameterScope { fn_id, body_id } => {
|
||||||
|
fn_id.hash_stable(hcx, hasher);
|
||||||
|
body_id.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
CodeExtentData::Remainder(block_remainder) => {
|
||||||
|
block_remainder.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
|
||||||
|
block,
|
||||||
|
first_statement_index
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
|
||||||
|
custom_kind
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::FreeRegion {
|
||||||
|
scope,
|
||||||
|
bound_region
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(enum ty::BoundRegion {
|
||||||
|
BrAnon(index),
|
||||||
|
BrNamed(def_id, name),
|
||||||
|
BrFresh(index),
|
||||||
|
BrEnv
|
||||||
|
});
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeVariants<'tcx>
|
||||||
|
{
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
use ty::TypeVariants::*;
|
||||||
|
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
match *self {
|
||||||
|
TyBool |
|
||||||
|
TyChar |
|
||||||
|
TyStr |
|
||||||
|
TyNever => {
|
||||||
|
// Nothing more to hash.
|
||||||
|
}
|
||||||
|
TyInt(int_ty) => {
|
||||||
|
int_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyUint(uint_ty) => {
|
||||||
|
uint_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyFloat(float_ty) => {
|
||||||
|
float_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyAdt(adt_def, substs) => {
|
||||||
|
adt_def.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyArray(inner_ty, len) => {
|
||||||
|
inner_ty.hash_stable(hcx, hasher);
|
||||||
|
len.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TySlice(inner_ty) => {
|
||||||
|
inner_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyRawPtr(pointee_ty) => {
|
||||||
|
pointee_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyRef(region, pointee_ty) => {
|
||||||
|
region.hash_stable(hcx, hasher);
|
||||||
|
pointee_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyFnDef(def_id, substs, ref sig) => {
|
||||||
|
def_id.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
sig.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyFnPtr(ref sig) => {
|
||||||
|
sig.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyDynamic(ref existential_predicates, region) => {
|
||||||
|
existential_predicates.hash_stable(hcx, hasher);
|
||||||
|
region.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyClosure(def_id, closure_substs) => {
|
||||||
|
def_id.hash_stable(hcx, hasher);
|
||||||
|
closure_substs.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyTuple(inner_tys, from_diverging_type_var) => {
|
||||||
|
inner_tys.hash_stable(hcx, hasher);
|
||||||
|
from_diverging_type_var.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyProjection(ref projection_ty) => {
|
||||||
|
projection_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyAnon(def_id, substs) => {
|
||||||
|
def_id.hash_stable(hcx, hasher);
|
||||||
|
substs.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
TyParam(param_ty) => {
|
||||||
|
param_ty.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
TyError |
|
||||||
|
TyInfer(..) => {
|
||||||
|
bug!("ty::TypeVariants::hash_stable() - Unexpected variant.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::ParamTy {
|
||||||
|
idx,
|
||||||
|
name
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
|
||||||
|
ty,
|
||||||
|
mutbl
|
||||||
|
});
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::ExistentialPredicate<'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 {
|
||||||
|
ty::ExistentialPredicate::Trait(ref trait_ref) => {
|
||||||
|
trait_ref.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::Projection(ref projection) => {
|
||||||
|
projection.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||||
|
def_id.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> {
|
||||||
|
def_id,
|
||||||
|
substs
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
|
||||||
|
trait_ref,
|
||||||
|
item_name,
|
||||||
|
ty
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'tcx> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a, 'tcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let ty::TypeckTables {
|
||||||
|
ref type_relative_path_defs,
|
||||||
|
ref node_types,
|
||||||
|
ref item_substs,
|
||||||
|
ref adjustments,
|
||||||
|
ref method_map,
|
||||||
|
ref upvar_capture_map,
|
||||||
|
ref closure_tys,
|
||||||
|
ref closure_kinds,
|
||||||
|
ref liberated_fn_sigs,
|
||||||
|
ref fru_field_types,
|
||||||
|
|
||||||
|
ref cast_kinds,
|
||||||
|
lints: _,
|
||||||
|
ref used_trait_imports,
|
||||||
|
tainted_by_errors,
|
||||||
|
ref free_region_map,
|
||||||
|
} = *self;
|
||||||
|
|
||||||
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, node_types);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, item_substs);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, adjustments);
|
||||||
|
|
||||||
|
ich::hash_stable_hashmap(hcx, hasher, method_map, |hcx, method_call| {
|
||||||
|
let ty::MethodCall {
|
||||||
|
expr_id,
|
||||||
|
autoderef
|
||||||
|
} = *method_call;
|
||||||
|
|
||||||
|
let def_id = hcx.tcx().hir.local_def_id(expr_id);
|
||||||
|
(hcx.def_path_hash(def_id), autoderef)
|
||||||
|
});
|
||||||
|
|
||||||
|
ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
|
||||||
|
let ty::UpvarId {
|
||||||
|
var_id,
|
||||||
|
closure_expr_id
|
||||||
|
} = *up_var_id;
|
||||||
|
|
||||||
|
let var_def_id = hcx.tcx().hir.local_def_id(var_id);
|
||||||
|
let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id);
|
||||||
|
(hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id))
|
||||||
|
});
|
||||||
|
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, closure_tys);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, closure_kinds);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, liberated_fn_sigs);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, fru_field_types);
|
||||||
|
ich::hash_stable_nodemap(hcx, hasher, cast_kinds);
|
||||||
|
|
||||||
|
ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
|
||||||
|
hcx.tcx().def_path_hash(*def_id)
|
||||||
|
});
|
||||||
|
|
||||||
|
tainted_by_errors.hash_stable(hcx, hasher);
|
||||||
|
free_region_map.hash_stable(hcx, hasher);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
pub use self::fingerprint::Fingerprint;
|
pub use self::fingerprint::Fingerprint;
|
||||||
pub use self::caching_codemap_view::CachingCodemapView;
|
pub use self::caching_codemap_view::CachingCodemapView;
|
||||||
pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
|
pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
|
||||||
|
hash_stable_hashset, hash_stable_nodemap};
|
||||||
mod fingerprint;
|
mod fingerprint;
|
||||||
mod caching_codemap_view;
|
mod caching_codemap_view;
|
||||||
mod hcx;
|
mod hcx;
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(discriminant_value)]
|
#![feature(discriminant_value)]
|
||||||
|
#![feature(sort_unstable)]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
|
@ -180,3 +180,7 @@ fn lub() {
|
||||||
map.relate_free_regions(frs[1], frs[2]);
|
map.relate_free_regions(frs[1], frs[2]);
|
||||||
assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2]));
|
assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct FreeRegionMap {
|
||||||
|
relation
|
||||||
|
});
|
||||||
|
|
|
@ -40,6 +40,12 @@ unsafe impl<T> Array for [T; 8] {
|
||||||
const LEN: usize = 8;
|
const LEN: usize = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<T> Array for [T; 32] {
|
||||||
|
type Element = T;
|
||||||
|
type PartialStorage = [ManuallyDrop<T>; 32];
|
||||||
|
const LEN: usize = 32;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ArrayVec<A: Array> {
|
pub struct ArrayVec<A: Array> {
|
||||||
count: usize,
|
count: usize,
|
||||||
values: A::PartialStorage
|
values: A::PartialStorage
|
||||||
|
|
|
@ -9,11 +9,14 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use bitvec::BitMatrix;
|
use bitvec::BitMatrix;
|
||||||
|
use stable_hasher::{HashStable, StableHasher, StableHasherResult};
|
||||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TransitiveRelation<T: Debug + PartialEq> {
|
pub struct TransitiveRelation<T: Debug + PartialEq> {
|
||||||
// List of elements. This is used to map from a T to a usize. We
|
// List of elements. This is used to map from a T to a usize. We
|
||||||
|
@ -334,6 +337,49 @@ impl<T> Decodable for TransitiveRelation<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
|
||||||
|
where T: HashStable<CTX> + PartialEq + Debug
|
||||||
|
{
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut CTX,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
// We are assuming here that the relation graph has been built in a
|
||||||
|
// deterministic way and we can just hash it the way it is.
|
||||||
|
let TransitiveRelation {
|
||||||
|
ref elements,
|
||||||
|
ref edges,
|
||||||
|
// "closure" is just a copy of the data above
|
||||||
|
closure: _
|
||||||
|
} = *self;
|
||||||
|
|
||||||
|
elements.hash_stable(hcx, hasher);
|
||||||
|
edges.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CTX> HashStable<CTX> for Edge {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut CTX,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let Edge {
|
||||||
|
ref source,
|
||||||
|
ref target,
|
||||||
|
} = *self;
|
||||||
|
|
||||||
|
source.hash_stable(hcx, hasher);
|
||||||
|
target.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CTX> HashStable<CTX> for Index {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut CTX,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
let Index(idx) = *self;
|
||||||
|
idx.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_one_step() {
|
fn test_one_step() {
|
||||||
let mut relation = TransitiveRelation::new();
|
let mut relation = TransitiveRelation::new();
|
||||||
|
|
|
@ -10,14 +10,12 @@
|
||||||
|
|
||||||
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
||||||
|
|
||||||
use encoder::EncodeContext;
|
use index_builder::EntryBuilder;
|
||||||
use schema::*;
|
use schema::*;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
|
|
||||||
use rustc_serialize::Encodable;
|
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Ast<'tcx> {
|
pub struct Ast<'tcx> {
|
||||||
pub body: Lazy<hir::Body>,
|
pub body: Lazy<hir::Body>,
|
||||||
|
@ -26,7 +24,14 @@ pub struct Ast<'tcx> {
|
||||||
pub rvalue_promotable_to_static: bool,
|
pub rvalue_promotable_to_static: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
impl_stable_hash_for!(struct Ast<'tcx> {
|
||||||
|
body,
|
||||||
|
tables,
|
||||||
|
nested_bodies,
|
||||||
|
rvalue_promotable_to_static
|
||||||
|
});
|
||||||
|
|
||||||
|
impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
|
||||||
let body = self.tcx.hir.body(body_id);
|
let body = self.tcx.hir.body(body_id);
|
||||||
let lazy_body = self.lazy(body);
|
let lazy_body = self.lazy(body);
|
||||||
|
@ -34,15 +39,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
let tables = self.tcx.body_tables(body_id);
|
let tables = self.tcx.body_tables(body_id);
|
||||||
let lazy_tables = self.lazy(tables);
|
let lazy_tables = self.lazy(tables);
|
||||||
|
|
||||||
let nested_pos = self.position();
|
let mut visitor = NestedBodyCollector {
|
||||||
let nested_count = {
|
tcx: self.tcx,
|
||||||
let mut visitor = NestedBodyEncodingVisitor {
|
bodies_found: Vec::new(),
|
||||||
ecx: self,
|
|
||||||
count: 0,
|
|
||||||
};
|
};
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
visitor.count
|
let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
|
||||||
};
|
|
||||||
|
|
||||||
let rvalue_promotable_to_static =
|
let rvalue_promotable_to_static =
|
||||||
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
|
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
|
||||||
|
@ -50,27 +52,25 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
self.lazy(&Ast {
|
self.lazy(&Ast {
|
||||||
body: lazy_body,
|
body: lazy_body,
|
||||||
tables: lazy_tables,
|
tables: lazy_tables,
|
||||||
nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
|
nested_bodies: lazy_nested_bodies,
|
||||||
rvalue_promotable_to_static: rvalue_promotable_to_static
|
rvalue_promotable_to_static: rvalue_promotable_to_static
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
|
struct NestedBodyCollector<'a, 'tcx: 'a> {
|
||||||
ecx: &'a mut EncodeContext<'b, 'tcx>,
|
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
count: usize,
|
bodies_found: Vec<&'tcx hir::Body>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
|
||||||
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
NestedVisitorMap::None
|
NestedVisitorMap::None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
fn visit_nested_body(&mut self, body: hir::BodyId) {
|
||||||
let body = self.ecx.tcx.hir.body(body);
|
let body = self.tcx.hir.body(body);
|
||||||
body.encode(self.ecx).unwrap();
|
self.bodies_found.push(body);
|
||||||
self.count += 1;
|
|
||||||
|
|
||||||
self.visit_body(body);
|
self.visit_body(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use schema::*;
|
||||||
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
|
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
|
||||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
|
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
|
||||||
use rustc::hir::map::definitions::DefPathTable;
|
use rustc::hir::map::definitions::DefPathTable;
|
||||||
|
use rustc::ich;
|
||||||
use rustc::middle::dependency_format::Linkage;
|
use rustc::middle::dependency_format::Linkage;
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
|
@ -42,7 +43,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
|
||||||
use rustc::hir::intravisit;
|
use rustc::hir::intravisit;
|
||||||
|
|
||||||
use super::index_builder::{FromId, IndexBuilder, Untracked};
|
use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder};
|
||||||
|
|
||||||
pub struct EncodeContext<'a, 'tcx: 'a> {
|
pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||||
opaque: opaque::Encoder<'a>,
|
opaque: opaque::Encoder<'a>,
|
||||||
|
@ -54,6 +55,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||||
lazy_state: LazyState,
|
lazy_state: LazyState,
|
||||||
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
|
||||||
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||||
|
|
||||||
|
pub metadata_hashes: Vec<(DefIndex, ich::Fingerprint)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! encoder_methods {
|
macro_rules! encoder_methods {
|
||||||
|
@ -172,7 +175,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
|
pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
|
||||||
where I: IntoIterator<Item = T>,
|
where I: IntoIterator<Item = T>,
|
||||||
T: Encodable
|
T: Encodable
|
||||||
{
|
{
|
||||||
|
@ -184,7 +187,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
|
pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
|
||||||
where I: IntoIterator<Item = &'b T>,
|
where I: IntoIterator<Item = &'b T>,
|
||||||
T: 'b + Encodable
|
T: 'b + Encodable
|
||||||
{
|
{
|
||||||
|
@ -233,10 +236,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
|
fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
|
self.lazy_seq_from_slice(&tcx.item_variances(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
|
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
|
||||||
|
@ -305,7 +310,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
|
|
||||||
let data = ModData {
|
let data = ModData {
|
||||||
reexports: match tcx.export_map.get(&id) {
|
reexports: match tcx.export_map.get(&id) {
|
||||||
Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
|
Some(exports) if *vis == hir::Public => {
|
||||||
|
self.lazy_seq_from_slice(exports.as_slice())
|
||||||
|
}
|
||||||
_ => LazySeq::empty(),
|
_ => LazySeq::empty(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -339,14 +346,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
for (variant_index, variant) in def.variants.iter().enumerate() {
|
for (variant_index, variant) in def.variants.iter().enumerate() {
|
||||||
for (field_index, field) in variant.fields.iter().enumerate() {
|
for (field_index, field) in variant.fields.iter().enumerate() {
|
||||||
self.record(field.did,
|
self.record(field.did,
|
||||||
EncodeContext::encode_field,
|
EntryBuilder::encode_field,
|
||||||
(adt_def_id, Untracked((variant_index, field_index))));
|
(adt_def_id, Untracked((variant_index, field_index))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
/// Encode data for the given field of the given variant of the
|
/// Encode data for the given field of the given variant of the
|
||||||
/// given ADT. The indices of the variant/field are untracked:
|
/// given ADT. The indices of the variant/field are untracked:
|
||||||
/// this is ok because we will have to lookup the adt-def by its
|
/// this is ok because we will have to lookup the adt-def by its
|
||||||
|
@ -907,7 +914,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
let def = self.tcx.lookup_adt_def(def_id);
|
let def = self.tcx.lookup_adt_def(def_id);
|
||||||
for (i, variant) in def.variants.iter().enumerate() {
|
for (i, variant) in def.variants.iter().enumerate() {
|
||||||
self.record(variant.did,
|
self.record(variant.did,
|
||||||
EncodeContext::encode_enum_variant_info,
|
EntryBuilder::encode_enum_variant_info,
|
||||||
(def_id, Untracked(i)));
|
(def_id, Untracked(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -918,7 +925,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
if !struct_def.is_struct() {
|
if !struct_def.is_struct() {
|
||||||
let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
|
let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
|
||||||
self.record(ctor_def_id,
|
self.record(ctor_def_id,
|
||||||
EncodeContext::encode_struct_ctor,
|
EntryBuilder::encode_struct_ctor,
|
||||||
(def_id, ctor_def_id));
|
(def_id, ctor_def_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,14 +935,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
hir::ItemImpl(..) => {
|
hir::ItemImpl(..) => {
|
||||||
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
||||||
self.record(trait_item_def_id,
|
self.record(trait_item_def_id,
|
||||||
EncodeContext::encode_info_for_impl_item,
|
EntryBuilder::encode_info_for_impl_item,
|
||||||
trait_item_def_id);
|
trait_item_def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemTrait(..) => {
|
hir::ItemTrait(..) => {
|
||||||
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
|
||||||
self.record(item_def_id,
|
self.record(item_def_id,
|
||||||
EncodeContext::encode_info_for_trait_item,
|
EntryBuilder::encode_info_for_trait_item,
|
||||||
item_def_id);
|
item_def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -943,7 +950,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
fn encode_info_for_foreign_item(&mut self,
|
fn encode_info_for_foreign_item(&mut self,
|
||||||
(def_id, nitem): (DefId, &hir::ForeignItem))
|
(def_id, nitem): (DefId, &hir::ForeignItem))
|
||||||
-> Entry<'tcx> {
|
-> Entry<'tcx> {
|
||||||
|
@ -1002,7 +1009,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemExternCrate(_) |
|
hir::ItemExternCrate(_) |
|
||||||
hir::ItemUse(..) => (), // ignore these
|
hir::ItemUse(..) => (), // ignore these
|
||||||
_ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
|
_ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)),
|
||||||
}
|
}
|
||||||
self.index.encode_addl_info_for_item(item);
|
self.index.encode_addl_info_for_item(item);
|
||||||
}
|
}
|
||||||
|
@ -1010,7 +1017,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
|
||||||
intravisit::walk_foreign_item(self, ni);
|
intravisit::walk_foreign_item(self, ni);
|
||||||
let def_id = self.index.tcx.hir.local_def_id(ni.id);
|
let def_id = self.index.tcx.hir.local_def_id(ni.id);
|
||||||
self.index.record(def_id,
|
self.index.record(def_id,
|
||||||
EncodeContext::encode_info_for_foreign_item,
|
EntryBuilder::encode_info_for_foreign_item,
|
||||||
(def_id, ni));
|
(def_id, ni));
|
||||||
}
|
}
|
||||||
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
||||||
|
@ -1023,7 +1030,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
|
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
|
||||||
let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
|
let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
|
||||||
self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
|
self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,14 +1039,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
for ty_param in &generics.ty_params {
|
for ty_param in &generics.ty_params {
|
||||||
let def_id = self.tcx.hir.local_def_id(ty_param.id);
|
let def_id = self.tcx.hir.local_def_id(ty_param.id);
|
||||||
let has_default = Untracked(ty_param.default.is_some());
|
let has_default = Untracked(ty_param.default.is_some());
|
||||||
self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
|
self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
|
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
|
||||||
if let hir::TyImplTrait(_) = ty.node {
|
if let hir::TyImplTrait(_) = ty.node {
|
||||||
let def_id = self.tcx.hir.local_def_id(ty.id);
|
let def_id = self.tcx.hir.local_def_id(ty.id);
|
||||||
self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id);
|
self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,14 +1054,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprClosure(..) => {
|
hir::ExprClosure(..) => {
|
||||||
let def_id = self.tcx.hir.local_def_id(expr.id);
|
let def_id = self.tcx.hir.local_def_id(expr.id);
|
||||||
self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
|
self.record(def_id, EntryBuilder::encode_info_for_closure, def_id);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
fn encode_info_for_ty_param(&mut self,
|
fn encode_info_for_ty_param(&mut self,
|
||||||
(def_id, Untracked(has_default)): (DefId, Untracked<bool>))
|
(def_id, Untracked(has_default)): (DefId, Untracked<bool>))
|
||||||
-> Entry<'tcx> {
|
-> Entry<'tcx> {
|
||||||
|
@ -1133,11 +1140,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
|
||||||
|
self.lazy_seq_from_slice(attrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
fn encode_info_for_items(&mut self) -> Index {
|
fn encode_info_for_items(&mut self) -> Index {
|
||||||
let krate = self.tcx.hir.krate();
|
let krate = self.tcx.hir.krate();
|
||||||
let mut index = IndexBuilder::new(self);
|
let mut index = IndexBuilder::new(self);
|
||||||
index.record(DefId::local(CRATE_DEF_INDEX),
|
index.record(DefId::local(CRATE_DEF_INDEX),
|
||||||
EncodeContext::encode_info_for_mod,
|
EntryBuilder::encode_info_for_mod,
|
||||||
FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
|
FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
|
||||||
let mut visitor = EncodeVisitor { index: index };
|
let mut visitor = EncodeVisitor { index: index };
|
||||||
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
|
||||||
|
@ -1147,10 +1160,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
visitor.index.into_items()
|
visitor.index.into_items()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
|
|
||||||
self.lazy_seq_ref(attrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
|
fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
|
||||||
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
|
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
|
||||||
// Pull the cnums and name,vers,hash out of cstore
|
// Pull the cnums and name,vers,hash out of cstore
|
||||||
|
@ -1298,7 +1307,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
None => LazySeq::empty(),
|
None => LazySeq::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
|
fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
|
||||||
let mut i = self.position();
|
let mut i = self.position();
|
||||||
let crate_deps = self.encode_crate_deps();
|
let crate_deps = self.encode_crate_deps();
|
||||||
|
@ -1448,6 +1459,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
lazy_state: LazyState::NoNode,
|
lazy_state: LazyState::NoNode,
|
||||||
type_shorthands: Default::default(),
|
type_shorthands: Default::default(),
|
||||||
predicate_shorthands: Default::default(),
|
predicate_shorthands: Default::default(),
|
||||||
|
metadata_hashes: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Encode the rustc version string in a predictable location.
|
// Encode the rustc version string in a predictable location.
|
||||||
|
|
|
@ -59,14 +59,19 @@ use encoder::EncodeContext;
|
||||||
use index::Index;
|
use index::Index;
|
||||||
use schema::*;
|
use schema::*;
|
||||||
|
|
||||||
use rustc::dep_graph::DepNode;
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::ich::{StableHashingContext, Fingerprint};
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
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.
|
/// Builder that can encode new items, adding them into the index.
|
||||||
/// Item encoding cannot be nested.
|
/// Item encoding cannot be nested.
|
||||||
pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
|
pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
|
||||||
|
@ -112,16 +117,29 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
/// holds, and that it is therefore not gaining "secret" access to
|
/// holds, and that it is therefore not gaining "secret" access to
|
||||||
/// bits of HIR or other state that would not be trackd by the
|
/// bits of HIR or other state that would not be trackd by the
|
||||||
/// content system.
|
/// content system.
|
||||||
pub fn record<DATA>(&mut self,
|
pub fn record<'x, DATA>(&'x mut self,
|
||||||
id: DefId,
|
id: DefId,
|
||||||
op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>,
|
op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
|
||||||
data: DATA)
|
data: DATA)
|
||||||
where DATA: DepGraphRead
|
where DATA: DepGraphRead
|
||||||
{
|
{
|
||||||
let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
|
let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
|
||||||
data.read(self.tcx);
|
data.read(self.tcx);
|
||||||
let entry = op(&mut self.ecx, data);
|
|
||||||
self.items.record(id, self.ecx.lazy(&entry));
|
assert!(id.is_local());
|
||||||
|
let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
|
||||||
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
|
let entry = op(&mut entry_builder, data);
|
||||||
|
let entry = entry_builder.ecx.lazy(&entry);
|
||||||
|
entry_builder.finish(id);
|
||||||
|
self.items.record(id, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_items(self) -> Index {
|
pub fn into_items(self) -> Index {
|
||||||
|
@ -223,3 +241,48 @@ impl<T> DepGraphRead for FromId<T> {
|
||||||
tcx.hir.read(self.0);
|
tcx.hir.read(self.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
self.ecx.lazy(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
|
#![feature(discriminant_value)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
|
@ -28,6 +28,9 @@ use syntax_pos::{self, Span};
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
|
||||||
|
StableHasherResult};
|
||||||
|
|
||||||
pub fn rustc_version() -> String {
|
pub fn rustc_version() -> String {
|
||||||
format!("rustc {}",
|
format!("rustc {}",
|
||||||
option_env!("CFG_VERSION").unwrap_or("unknown version"))
|
option_env!("CFG_VERSION").unwrap_or("unknown version"))
|
||||||
|
@ -100,6 +103,15 @@ impl<T> Clone for Lazy<T> {
|
||||||
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
|
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
|
||||||
impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
|
impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A sequence of type T referred to by its absolute position
|
/// A sequence of type T referred to by its absolute position
|
||||||
/// in the metadata and length, and which can be decoded lazily.
|
/// in the metadata and length, and which can be decoded lazily.
|
||||||
/// The sequence is a single node for the purposes of `Lazy`.
|
/// The sequence is a single node for the purposes of `Lazy`.
|
||||||
|
@ -148,6 +160,15 @@ impl<T> Clone for LazySeq<T> {
|
||||||
impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
|
impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
|
||||||
impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
|
impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Encoding / decoding state for `Lazy` and `LazySeq`.
|
/// Encoding / decoding state for `Lazy` and `LazySeq`.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum LazyState {
|
pub enum LazyState {
|
||||||
|
@ -251,17 +272,23 @@ pub struct ModData {
|
||||||
pub reexports: LazySeq<def::Export>,
|
pub reexports: LazySeq<def::Export>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ModData { reexports });
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct MacroDef {
|
pub struct MacroDef {
|
||||||
pub body: String,
|
pub body: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct MacroDef { body });
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct FnData {
|
pub struct FnData {
|
||||||
pub constness: hir::Constness,
|
pub constness: hir::Constness,
|
||||||
pub arg_names: LazySeq<ast::Name>,
|
pub arg_names: LazySeq<ast::Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct FnData { constness, arg_names });
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct VariantData<'tcx> {
|
pub struct VariantData<'tcx> {
|
||||||
pub ctor_kind: CtorKind,
|
pub ctor_kind: CtorKind,
|
||||||
|
@ -273,6 +300,13 @@ pub struct VariantData<'tcx> {
|
||||||
pub struct_ctor: Option<DefIndex>,
|
pub struct_ctor: Option<DefIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct VariantData<'tcx> {
|
||||||
|
ctor_kind,
|
||||||
|
discr,
|
||||||
|
evaluated_discr,
|
||||||
|
struct_ctor
|
||||||
|
});
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct TraitData<'tcx> {
|
pub struct TraitData<'tcx> {
|
||||||
pub unsafety: hir::Unsafety,
|
pub unsafety: hir::Unsafety,
|
||||||
|
@ -281,6 +315,13 @@ pub struct TraitData<'tcx> {
|
||||||
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
|
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct TraitData<'tcx> {
|
||||||
|
unsafety,
|
||||||
|
paren_sugar,
|
||||||
|
has_default_impl,
|
||||||
|
super_predicates
|
||||||
|
});
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ImplData<'tcx> {
|
pub struct ImplData<'tcx> {
|
||||||
pub polarity: hir::ImplPolarity,
|
pub polarity: hir::ImplPolarity,
|
||||||
|
@ -291,6 +332,14 @@ pub struct ImplData<'tcx> {
|
||||||
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
|
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(struct ImplData<'tcx> {
|
||||||
|
polarity,
|
||||||
|
parent_impl,
|
||||||
|
coerce_unsized_info,
|
||||||
|
trait_ref
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/// Describes whether the container of an associated item
|
/// Describes whether the container of an associated item
|
||||||
/// is a trait or an impl and whether, in a trait, it has
|
/// is a trait or an impl and whether, in a trait, it has
|
||||||
/// a default, or an in impl, whether it's marked "default".
|
/// a default, or an in impl, whether it's marked "default".
|
||||||
|
@ -302,6 +351,13 @@ pub enum AssociatedContainer {
|
||||||
ImplFinal,
|
ImplFinal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_stable_hash_for!(enum ::schema::AssociatedContainer {
|
||||||
|
TraitRequired,
|
||||||
|
TraitWithDefault,
|
||||||
|
ImplDefault,
|
||||||
|
ImplFinal
|
||||||
|
});
|
||||||
|
|
||||||
impl AssociatedContainer {
|
impl AssociatedContainer {
|
||||||
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
|
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -335,9 +391,11 @@ pub struct MethodData {
|
||||||
pub container: AssociatedContainer,
|
pub container: AssociatedContainer,
|
||||||
pub has_self: bool,
|
pub has_self: bool,
|
||||||
}
|
}
|
||||||
|
impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ClosureData<'tcx> {
|
pub struct ClosureData<'tcx> {
|
||||||
pub kind: ty::ClosureKind,
|
pub kind: ty::ClosureKind,
|
||||||
pub ty: Lazy<ty::PolyFnSig<'tcx>>,
|
pub ty: Lazy<ty::PolyFnSig<'tcx>>,
|
||||||
}
|
}
|
||||||
|
impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue