Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b5450ab

Browse files
committedApr 10, 2017
ICH: Hash everything that gets encoded into crate metadata.
1 parent 4489cd4 commit b5450ab

File tree

12 files changed

+576
-66
lines changed

12 files changed

+576
-66
lines changed
 

‎src/librustc/ich/hcx.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ use hir::def_id::DefId;
1313
use ich::{self, CachingCodemapView};
1414
use session::config::DebugInfoLevel::NoDebugInfo;
1515
use ty;
16+
use util::nodemap::NodeMap;
1617

1718
use std::hash as std_hash;
19+
use std::collections::{HashMap, HashSet};
1820

1921
use syntax::ast;
2022
use syntax::attr;
@@ -296,3 +298,53 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for Span {
296298
}
297299
}
298300
}
301+
302+
pub fn hash_stable_hashmap<'a, 'tcx, K, V, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
303+
hasher: &mut StableHasher<W>,
304+
map: &HashMap<K, V, R>,
305+
extract_stable_key: F)
306+
where K: Eq + std_hash::Hash,
307+
V: HashStable<StableHashingContext<'a, 'tcx>>,
308+
R: std_hash::BuildHasher,
309+
SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
310+
F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
311+
W: StableHasherResult,
312+
{
313+
let mut keys: Vec<_> = map.keys()
314+
.map(|k| (extract_stable_key(hcx, k), k))
315+
.collect();
316+
keys.sort_unstable_by_key(|&(ref stable_key, _)| stable_key.clone());
317+
keys.len().hash_stable(hcx, hasher);
318+
for (stable_key, key) in keys {
319+
stable_key.hash_stable(hcx, hasher);
320+
map[key].hash_stable(hcx, hasher);
321+
}
322+
}
323+
324+
pub fn hash_stable_hashset<'a, 'tcx, K, R, SK, F, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
325+
hasher: &mut StableHasher<W>,
326+
set: &HashSet<K, R>,
327+
extract_stable_key: F)
328+
where K: Eq + std_hash::Hash,
329+
R: std_hash::BuildHasher,
330+
SK: HashStable<StableHashingContext<'a, 'tcx>> + Ord + Clone,
331+
F: Fn(&mut StableHashingContext<'a, 'tcx>, &K) -> SK,
332+
W: StableHasherResult,
333+
{
334+
let mut keys: Vec<_> = set.iter()
335+
.map(|k| extract_stable_key(hcx, k))
336+
.collect();
337+
keys.sort_unstable();
338+
keys.hash_stable(hcx, hasher);
339+
}
340+
341+
pub fn hash_stable_nodemap<'a, 'tcx, V, W>(hcx: &mut StableHashingContext<'a, 'tcx>,
342+
hasher: &mut StableHasher<W>,
343+
map: &NodeMap<V>)
344+
where V: HashStable<StableHashingContext<'a, 'tcx>>,
345+
W: StableHasherResult,
346+
{
347+
hash_stable_hashmap(hcx, hasher, map, |hcx, node_id| {
348+
hcx.tcx.hir.definitions().node_to_hir_id(*node_id).local_id
349+
});
350+
}

‎src/librustc/ich/impls_ty.rs

Lines changed: 279 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,37 @@
1111
//! This module contains `HashStable` implementations for various data types
1212
//! from rustc::ty in no particular order.
1313
14-
use ich::StableHashingContext;
14+
use ich::{self, StableHashingContext, NodeIdHashingMode};
1515
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1616
StableHasherResult};
1717
use std::hash as std_hash;
1818
use std::mem;
1919
use ty;
2020

21-
22-
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Ty<'tcx> {
21+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TyS<'tcx> {
2322
fn hash_stable<W: StableHasherResult>(&self,
2423
hcx: &mut StableHashingContext<'a, 'tcx>,
2524
hasher: &mut StableHasher<W>) {
26-
let type_hash = hcx.tcx().type_id_hash(*self);
27-
type_hash.hash_stable(hcx, hasher);
25+
let ty::TyS {
26+
ref sty,
27+
28+
// The other fields just provide fast access to information that is
29+
// also contained in `sty`, so no need to hash them.
30+
..
31+
} = *self;
32+
33+
sty.hash_stable(hcx, hasher);
2834
}
2935
}
3036

3137
impl_stable_hash_for!(struct ty::ItemSubsts<'tcx> { substs });
3238

33-
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for ty::Slice<T>
39+
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a, 'tcx>> for &'tcx ty::Slice<T>
3440
where T: HashStable<StableHashingContext<'a, 'tcx>> {
3541
fn hash_stable<W: StableHasherResult>(&self,
3642
hcx: &mut StableHashingContext<'a, 'tcx>,
3743
hasher: &mut StableHasher<W>) {
38-
(&**self).hash_stable(hcx, hasher);
44+
(&self[..]).hash_stable(hcx, hasher);
3945
}
4046
}
4147

@@ -67,9 +73,13 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Region {
6773
index.hash_stable(hcx, hasher);
6874
name.hash_stable(hcx, hasher);
6975
}
76+
ty::ReScope(code_extent) => {
77+
code_extent.hash_stable(hcx, hasher);
78+
}
79+
ty::ReFree(ref free_region) => {
80+
free_region.hash_stable(hcx, hasher);
81+
}
7082
ty::ReLateBound(..) |
71-
ty::ReFree(..) |
72-
ty::ReScope(..) |
7383
ty::ReVar(..) |
7484
ty::ReSkolemized(..) => {
7585
bug!("TypeIdHasher: unexpected region {:?}", *self)
@@ -127,7 +137,6 @@ impl_stable_hash_for!(enum ty::BorrowKind {
127137
MutBorrow
128138
});
129139

130-
131140
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::UpvarCapture<'tcx> {
132141
fn hash_stable<W: StableHasherResult>(&self,
133142
hcx: &mut StableHashingContext<'a, 'tcx>,
@@ -223,7 +232,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::Predicate<'tcx
223232
}
224233
}
225234

226-
227235
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::AdtFlags {
228236
fn hash_stable<W: StableHasherResult>(&self,
229237
_: &mut StableHashingContext<'a, 'tcx>,
@@ -303,7 +311,6 @@ for ::middle::const_val::ConstVal<'tcx> {
303311

304312
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
305313

306-
307314
impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
308315
parent,
309316
predicates
@@ -413,3 +420,263 @@ impl_stable_hash_for!(struct ::middle::region::CallSiteScopeData {
413420
impl_stable_hash_for!(struct ty::DebruijnIndex {
414421
depth
415422
});
423+
424+
impl_stable_hash_for!(enum ty::cast::CastKind {
425+
CoercionCast,
426+
PtrPtrCast,
427+
PtrAddrCast,
428+
AddrPtrCast,
429+
NumericCast,
430+
EnumCast,
431+
PrimIntCast,
432+
U8CharCast,
433+
ArrayPtrCast,
434+
FnPtrPtrCast,
435+
FnPtrAddrCast
436+
});
437+
438+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtent
439+
{
440+
fn hash_stable<W: StableHasherResult>(&self,
441+
hcx: &mut StableHashingContext<'a, 'tcx>,
442+
hasher: &mut StableHasher<W>) {
443+
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
444+
hcx.tcx().region_maps.code_extent_data(*self).hash_stable(hcx, hasher);
445+
});
446+
}
447+
}
448+
449+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ::middle::region::CodeExtentData
450+
{
451+
fn hash_stable<W: StableHasherResult>(&self,
452+
hcx: &mut StableHashingContext<'a, 'tcx>,
453+
hasher: &mut StableHasher<W>) {
454+
use middle::region::CodeExtentData;
455+
456+
mem::discriminant(self).hash_stable(hcx, hasher);
457+
match *self {
458+
CodeExtentData::Misc(node_id) |
459+
CodeExtentData::DestructionScope(node_id) => {
460+
node_id.hash_stable(hcx, hasher);
461+
}
462+
CodeExtentData::CallSiteScope { fn_id, body_id } |
463+
CodeExtentData::ParameterScope { fn_id, body_id } => {
464+
fn_id.hash_stable(hcx, hasher);
465+
body_id.hash_stable(hcx, hasher);
466+
}
467+
CodeExtentData::Remainder(block_remainder) => {
468+
block_remainder.hash_stable(hcx, hasher);
469+
}
470+
}
471+
}
472+
}
473+
474+
impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
475+
block,
476+
first_statement_index
477+
});
478+
479+
impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
480+
custom_kind
481+
});
482+
483+
impl_stable_hash_for!(struct ty::FreeRegion {
484+
scope,
485+
bound_region
486+
});
487+
488+
impl_stable_hash_for!(enum ty::BoundRegion {
489+
BrAnon(index),
490+
BrNamed(def_id, name),
491+
BrFresh(index),
492+
BrEnv
493+
});
494+
495+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeVariants<'tcx>
496+
{
497+
fn hash_stable<W: StableHasherResult>(&self,
498+
hcx: &mut StableHashingContext<'a, 'tcx>,
499+
hasher: &mut StableHasher<W>) {
500+
use ty::TypeVariants::*;
501+
502+
mem::discriminant(self).hash_stable(hcx, hasher);
503+
match *self {
504+
TyBool |
505+
TyChar |
506+
TyStr |
507+
TyNever => {
508+
// Nothing more to hash.
509+
}
510+
TyInt(int_ty) => {
511+
int_ty.hash_stable(hcx, hasher);
512+
}
513+
TyUint(uint_ty) => {
514+
uint_ty.hash_stable(hcx, hasher);
515+
}
516+
TyFloat(float_ty) => {
517+
float_ty.hash_stable(hcx, hasher);
518+
}
519+
TyAdt(adt_def, substs) => {
520+
adt_def.hash_stable(hcx, hasher);
521+
substs.hash_stable(hcx, hasher);
522+
}
523+
TyArray(inner_ty, len) => {
524+
inner_ty.hash_stable(hcx, hasher);
525+
len.hash_stable(hcx, hasher);
526+
}
527+
TySlice(inner_ty) => {
528+
inner_ty.hash_stable(hcx, hasher);
529+
}
530+
TyRawPtr(pointee_ty) => {
531+
pointee_ty.hash_stable(hcx, hasher);
532+
}
533+
TyRef(region, pointee_ty) => {
534+
region.hash_stable(hcx, hasher);
535+
pointee_ty.hash_stable(hcx, hasher);
536+
}
537+
TyFnDef(def_id, substs, ref sig) => {
538+
def_id.hash_stable(hcx, hasher);
539+
substs.hash_stable(hcx, hasher);
540+
sig.hash_stable(hcx, hasher);
541+
}
542+
TyFnPtr(ref sig) => {
543+
sig.hash_stable(hcx, hasher);
544+
}
545+
TyDynamic(ref existential_predicates, region) => {
546+
existential_predicates.hash_stable(hcx, hasher);
547+
region.hash_stable(hcx, hasher);
548+
}
549+
TyClosure(def_id, closure_substs) => {
550+
def_id.hash_stable(hcx, hasher);
551+
closure_substs.hash_stable(hcx, hasher);
552+
}
553+
TyTuple(inner_tys, from_diverging_type_var) => {
554+
inner_tys.hash_stable(hcx, hasher);
555+
from_diverging_type_var.hash_stable(hcx, hasher);
556+
}
557+
TyProjection(ref projection_ty) => {
558+
projection_ty.hash_stable(hcx, hasher);
559+
}
560+
TyAnon(def_id, substs) => {
561+
def_id.hash_stable(hcx, hasher);
562+
substs.hash_stable(hcx, hasher);
563+
}
564+
TyParam(param_ty) => {
565+
param_ty.hash_stable(hcx, hasher);
566+
}
567+
568+
TyError |
569+
TyInfer(..) => {
570+
bug!("ty::TypeVariants::hash_stable() - Unexpected variant.")
571+
}
572+
}
573+
}
574+
}
575+
576+
impl_stable_hash_for!(struct ty::ParamTy {
577+
idx,
578+
name
579+
});
580+
581+
impl_stable_hash_for!(struct ty::TypeAndMut<'tcx> {
582+
ty,
583+
mutbl
584+
});
585+
586+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::ExistentialPredicate<'tcx>
587+
{
588+
fn hash_stable<W: StableHasherResult>(&self,
589+
hcx: &mut StableHashingContext<'a, 'tcx>,
590+
hasher: &mut StableHasher<W>) {
591+
mem::discriminant(self).hash_stable(hcx, hasher);
592+
match *self {
593+
ty::ExistentialPredicate::Trait(ref trait_ref) => {
594+
trait_ref.hash_stable(hcx, hasher);
595+
}
596+
ty::ExistentialPredicate::Projection(ref projection) => {
597+
projection.hash_stable(hcx, hasher);
598+
}
599+
ty::ExistentialPredicate::AutoTrait(def_id) => {
600+
def_id.hash_stable(hcx, hasher);
601+
}
602+
}
603+
}
604+
}
605+
606+
impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> {
607+
def_id,
608+
substs
609+
});
610+
611+
impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
612+
trait_ref,
613+
item_name,
614+
ty
615+
});
616+
617+
618+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::TypeckTables<'tcx> {
619+
fn hash_stable<W: StableHasherResult>(&self,
620+
hcx: &mut StableHashingContext<'a, 'tcx>,
621+
hasher: &mut StableHasher<W>) {
622+
let ty::TypeckTables {
623+
ref type_relative_path_defs,
624+
ref node_types,
625+
ref item_substs,
626+
ref adjustments,
627+
ref method_map,
628+
ref upvar_capture_map,
629+
ref closure_tys,
630+
ref closure_kinds,
631+
ref liberated_fn_sigs,
632+
ref fru_field_types,
633+
634+
ref cast_kinds,
635+
lints: _,
636+
ref used_trait_imports,
637+
tainted_by_errors,
638+
ref free_region_map,
639+
} = *self;
640+
641+
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
642+
ich::hash_stable_nodemap(hcx, hasher, type_relative_path_defs);
643+
ich::hash_stable_nodemap(hcx, hasher, node_types);
644+
ich::hash_stable_nodemap(hcx, hasher, item_substs);
645+
ich::hash_stable_nodemap(hcx, hasher, adjustments);
646+
647+
ich::hash_stable_hashmap(hcx, hasher, method_map, |hcx, method_call| {
648+
let ty::MethodCall {
649+
expr_id,
650+
autoderef
651+
} = *method_call;
652+
653+
let def_id = hcx.tcx().hir.local_def_id(expr_id);
654+
(hcx.def_path_hash(def_id), autoderef)
655+
});
656+
657+
ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| {
658+
let ty::UpvarId {
659+
var_id,
660+
closure_expr_id
661+
} = *up_var_id;
662+
663+
let var_def_id = hcx.tcx().hir.local_def_id(var_id);
664+
let closure_def_id = hcx.tcx().hir.local_def_id(closure_expr_id);
665+
(hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id))
666+
});
667+
668+
ich::hash_stable_nodemap(hcx, hasher, closure_tys);
669+
ich::hash_stable_nodemap(hcx, hasher, closure_kinds);
670+
ich::hash_stable_nodemap(hcx, hasher, liberated_fn_sigs);
671+
ich::hash_stable_nodemap(hcx, hasher, fru_field_types);
672+
ich::hash_stable_nodemap(hcx, hasher, cast_kinds);
673+
674+
ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| {
675+
hcx.tcx().def_path_hash(*def_id)
676+
});
677+
678+
tainted_by_errors.hash_stable(hcx, hasher);
679+
free_region_map.hash_stable(hcx, hasher);
680+
})
681+
}
682+
}

‎src/librustc/ich/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
1313
pub use self::fingerprint::Fingerprint;
1414
pub use self::caching_codemap_view::CachingCodemapView;
15-
pub use self::hcx::{StableHashingContext, NodeIdHashingMode};
16-
15+
pub use self::hcx::{StableHashingContext, NodeIdHashingMode, hash_stable_hashmap,
16+
hash_stable_hashset, hash_stable_nodemap};
1717
mod fingerprint;
1818
mod caching_codemap_view;
1919
mod hcx;

‎src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#![feature(staged_api)]
4343
#![feature(unboxed_closures)]
4444
#![feature(discriminant_value)]
45+
#![feature(sort_unstable)]
4546

4647
extern crate arena;
4748
extern crate core;

‎src/librustc/middle/free_region.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,7 @@ fn lub() {
180180
map.relate_free_regions(frs[1], frs[2]);
181181
assert_eq!(map.lub_free_regions(frs[0], frs[1]), ty::ReFree(frs[2]));
182182
}
183+
184+
impl_stable_hash_for!(struct FreeRegionMap {
185+
relation
186+
});

‎src/librustc_data_structures/array_vec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ unsafe impl<T> Array for [T; 8] {
3939
const LEN: usize = 8;
4040
}
4141

42+
unsafe impl<T> Array for [T; 32] {
43+
type Element = T;
44+
type PartialStorage = [ManuallyDrop<T>; 32];
45+
const LEN: usize = 32;
46+
}
47+
4248
pub struct ArrayVec<A: Array> {
4349
count: usize,
4450
values: A::PartialStorage

‎src/librustc_data_structures/transitive_relation.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
// except according to those terms.
1010

1111
use bitvec::BitMatrix;
12+
use stable_hasher::{HashStable, StableHasher, StableHasherResult};
1213
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
1314
use std::cell::RefCell;
1415
use std::fmt::Debug;
1516
use std::mem;
1617

18+
19+
1720
#[derive(Clone)]
1821
pub struct TransitiveRelation<T: Debug + PartialEq> {
1922
// 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>
334337
}
335338
}
336339

340+
impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
341+
where T: HashStable<CTX> + PartialEq + Debug
342+
{
343+
fn hash_stable<W: StableHasherResult>(&self,
344+
hcx: &mut CTX,
345+
hasher: &mut StableHasher<W>) {
346+
// We are assuming here that the relation graph has been built in a
347+
// deterministic way and we can just hash it the way it is.
348+
let TransitiveRelation {
349+
ref elements,
350+
ref edges,
351+
// "closure" is just a copy of the data above
352+
closure: _
353+
} = *self;
354+
355+
elements.hash_stable(hcx, hasher);
356+
edges.hash_stable(hcx, hasher);
357+
}
358+
}
359+
360+
impl<CTX> HashStable<CTX> for Edge {
361+
fn hash_stable<W: StableHasherResult>(&self,
362+
hcx: &mut CTX,
363+
hasher: &mut StableHasher<W>) {
364+
let Edge {
365+
ref source,
366+
ref target,
367+
} = *self;
368+
369+
source.hash_stable(hcx, hasher);
370+
target.hash_stable(hcx, hasher);
371+
}
372+
}
373+
374+
impl<CTX> HashStable<CTX> for Index {
375+
fn hash_stable<W: StableHasherResult>(&self,
376+
hcx: &mut CTX,
377+
hasher: &mut StableHasher<W>) {
378+
let Index(idx) = *self;
379+
idx.hash_stable(hcx, hasher);
380+
}
381+
}
382+
337383
#[test]
338384
fn test_one_step() {
339385
let mut relation = TransitiveRelation::new();

‎src/librustc_metadata/astencode.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@
1010

1111
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
1212

13-
use encoder::EncodeContext;
13+
use index_builder::EntryBuilder;
1414
use schema::*;
1515

1616
use rustc::hir;
1717
use rustc::ty;
1818

19-
use rustc_serialize::Encodable;
20-
2119
#[derive(RustcEncodable, RustcDecodable)]
2220
pub struct Ast<'tcx> {
2321
pub body: Lazy<hir::Body>,
@@ -26,51 +24,53 @@ pub struct Ast<'tcx> {
2624
pub rvalue_promotable_to_static: bool,
2725
}
2826

29-
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
27+
impl_stable_hash_for!(struct Ast<'tcx> {
28+
body,
29+
tables,
30+
nested_bodies,
31+
rvalue_promotable_to_static
32+
});
33+
34+
impl<'a, 'b, 'tcx> EntryBuilder<'a, 'b, 'tcx> {
3035
pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
3136
let body = self.tcx.hir.body(body_id);
3237
let lazy_body = self.lazy(body);
3338

3439
let tables = self.tcx.body_tables(body_id);
3540
let lazy_tables = self.lazy(tables);
3641

37-
let nested_pos = self.position();
38-
let nested_count = {
39-
let mut visitor = NestedBodyEncodingVisitor {
40-
ecx: self,
41-
count: 0,
42-
};
43-
visitor.visit_body(body);
44-
visitor.count
42+
let mut visitor = NestedBodyCollector {
43+
tcx: self.tcx,
44+
bodies_found: Vec::new(),
4545
};
46+
visitor.visit_body(body);
47+
let lazy_nested_bodies = self.lazy_seq_ref_from_slice(&visitor.bodies_found);
4648

4749
let rvalue_promotable_to_static =
4850
self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id];
4951

5052
self.lazy(&Ast {
5153
body: lazy_body,
5254
tables: lazy_tables,
53-
nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count),
55+
nested_bodies: lazy_nested_bodies,
5456
rvalue_promotable_to_static: rvalue_promotable_to_static
5557
})
5658
}
5759
}
5860

59-
struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> {
60-
ecx: &'a mut EncodeContext<'b, 'tcx>,
61-
count: usize,
61+
struct NestedBodyCollector<'a, 'tcx: 'a> {
62+
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
63+
bodies_found: Vec<&'tcx hir::Body>,
6264
}
6365

64-
impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> {
66+
impl<'a, 'tcx: 'a> Visitor<'tcx> for NestedBodyCollector<'a, 'tcx> {
6567
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
6668
NestedVisitorMap::None
6769
}
6870

6971
fn visit_nested_body(&mut self, body: hir::BodyId) {
70-
let body = self.ecx.tcx.hir.body(body);
71-
body.encode(self.ecx).unwrap();
72-
self.count += 1;
73-
72+
let body = self.tcx.hir.body(body);
73+
self.bodies_found.push(body);
7474
self.visit_body(body);
7575
}
7676
}

‎src/librustc_metadata/encoder.rs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use schema::*;
1515
use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
1616
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
1717
use rustc::hir::map::definitions::DefPathTable;
18+
use rustc::ich;
1819
use rustc::middle::dependency_format::Linkage;
1920
use rustc::middle::lang_items;
2021
use rustc::mir;
@@ -42,7 +43,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
4243
use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
4344
use rustc::hir::intravisit;
4445

45-
use super::index_builder::{FromId, IndexBuilder, Untracked};
46+
use super::index_builder::{FromId, IndexBuilder, Untracked, EntryBuilder};
4647

4748
pub struct EncodeContext<'a, 'tcx: 'a> {
4849
opaque: opaque::Encoder<'a>,
@@ -54,6 +55,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
5455
lazy_state: LazyState,
5556
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
5657
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
58+
59+
pub metadata_hashes: Vec<(DefIndex, ich::Fingerprint)>,
5760
}
5861

5962
macro_rules! encoder_methods {
@@ -172,7 +175,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
172175
})
173176
}
174177

175-
fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
178+
pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
176179
where I: IntoIterator<Item = T>,
177180
T: Encodable
178181
{
@@ -184,7 +187,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
184187
})
185188
}
186189

187-
fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
190+
pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T>
188191
where I: IntoIterator<Item = &'b T>,
189192
T: 'b + Encodable
190193
{
@@ -233,10 +236,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
233236

234237
Ok(())
235238
}
239+
}
236240

241+
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
237242
fn encode_item_variances(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
238243
let tcx = self.tcx;
239-
self.lazy_seq(tcx.item_variances(def_id).iter().cloned())
244+
self.lazy_seq_from_slice(&tcx.item_variances(def_id))
240245
}
241246

242247
fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
@@ -305,7 +310,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
305310

306311
let data = ModData {
307312
reexports: match tcx.export_map.get(&id) {
308-
Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
313+
Some(exports) if *vis == hir::Public => {
314+
self.lazy_seq_from_slice(exports.as_slice())
315+
}
309316
_ => LazySeq::empty(),
310317
},
311318
};
@@ -339,14 +346,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
339346
for (variant_index, variant) in def.variants.iter().enumerate() {
340347
for (field_index, field) in variant.fields.iter().enumerate() {
341348
self.record(field.did,
342-
EncodeContext::encode_field,
349+
EntryBuilder::encode_field,
343350
(adt_def_id, Untracked((variant_index, field_index))));
344351
}
345352
}
346353
}
347354
}
348355

349-
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
356+
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
350357
/// Encode data for the given field of the given variant of the
351358
/// given ADT. The indices of the variant/field are untracked:
352359
/// 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> {
907914
let def = self.tcx.lookup_adt_def(def_id);
908915
for (i, variant) in def.variants.iter().enumerate() {
909916
self.record(variant.did,
910-
EncodeContext::encode_enum_variant_info,
917+
EntryBuilder::encode_enum_variant_info,
911918
(def_id, Untracked(i)));
912919
}
913920
}
@@ -918,7 +925,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
918925
if !struct_def.is_struct() {
919926
let ctor_def_id = self.tcx.hir.local_def_id(struct_def.id());
920927
self.record(ctor_def_id,
921-
EncodeContext::encode_struct_ctor,
928+
EntryBuilder::encode_struct_ctor,
922929
(def_id, ctor_def_id));
923930
}
924931
}
@@ -928,22 +935,22 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
928935
hir::ItemImpl(..) => {
929936
for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
930937
self.record(trait_item_def_id,
931-
EncodeContext::encode_info_for_impl_item,
938+
EntryBuilder::encode_info_for_impl_item,
932939
trait_item_def_id);
933940
}
934941
}
935942
hir::ItemTrait(..) => {
936943
for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
937944
self.record(item_def_id,
938-
EncodeContext::encode_info_for_trait_item,
945+
EntryBuilder::encode_info_for_trait_item,
939946
item_def_id);
940947
}
941948
}
942949
}
943950
}
944951
}
945952

946-
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
953+
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
947954
fn encode_info_for_foreign_item(&mut self,
948955
(def_id, nitem): (DefId, &hir::ForeignItem))
949956
-> Entry<'tcx> {
@@ -1002,15 +1009,15 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
10021009
match item.node {
10031010
hir::ItemExternCrate(_) |
10041011
hir::ItemUse(..) => (), // ignore these
1005-
_ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
1012+
_ => self.index.record(def_id, EntryBuilder::encode_info_for_item, (def_id, item)),
10061013
}
10071014
self.index.encode_addl_info_for_item(item);
10081015
}
10091016
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
10101017
intravisit::walk_foreign_item(self, ni);
10111018
let def_id = self.index.tcx.hir.local_def_id(ni.id);
10121019
self.index.record(def_id,
1013-
EncodeContext::encode_info_for_foreign_item,
1020+
EntryBuilder::encode_info_for_foreign_item,
10141021
(def_id, ni));
10151022
}
10161023
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
@@ -1023,7 +1030,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
10231030
}
10241031
fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
10251032
let def_id = self.index.tcx.hir.local_def_id(macro_def.id);
1026-
self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
1033+
self.index.record(def_id, EntryBuilder::encode_info_for_macro_def, macro_def);
10271034
}
10281035
}
10291036

@@ -1032,29 +1039,29 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
10321039
for ty_param in &generics.ty_params {
10331040
let def_id = self.tcx.hir.local_def_id(ty_param.id);
10341041
let has_default = Untracked(ty_param.default.is_some());
1035-
self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
1042+
self.record(def_id, EntryBuilder::encode_info_for_ty_param, (def_id, has_default));
10361043
}
10371044
}
10381045

10391046
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
10401047
if let hir::TyImplTrait(_) = ty.node {
10411048
let def_id = self.tcx.hir.local_def_id(ty.id);
1042-
self.record(def_id, EncodeContext::encode_info_for_anon_ty, def_id);
1049+
self.record(def_id, EntryBuilder::encode_info_for_anon_ty, def_id);
10431050
}
10441051
}
10451052

10461053
fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
10471054
match expr.node {
10481055
hir::ExprClosure(..) => {
10491056
let def_id = self.tcx.hir.local_def_id(expr.id);
1050-
self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
1057+
self.record(def_id, EntryBuilder::encode_info_for_closure, def_id);
10511058
}
10521059
_ => {}
10531060
}
10541061
}
10551062
}
10561063

1057-
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
1064+
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
10581065
fn encode_info_for_ty_param(&mut self,
10591066
(def_id, Untracked(has_default)): (DefId, Untracked<bool>))
10601067
-> Entry<'tcx> {
@@ -1133,11 +1140,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11331140
}
11341141
}
11351142

1143+
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
1144+
self.lazy_seq_from_slice(attrs)
1145+
}
1146+
}
1147+
1148+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11361149
fn encode_info_for_items(&mut self) -> Index {
11371150
let krate = self.tcx.hir.krate();
11381151
let mut index = IndexBuilder::new(self);
11391152
index.record(DefId::local(CRATE_DEF_INDEX),
1140-
EncodeContext::encode_info_for_mod,
1153+
EntryBuilder::encode_info_for_mod,
11411154
FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public)));
11421155
let mut visitor = EncodeVisitor { index: index };
11431156
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
@@ -1147,10 +1160,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11471160
visitor.index.into_items()
11481161
}
11491162

1150-
fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
1151-
self.lazy_seq_ref(attrs)
1152-
}
1153-
11541163
fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
11551164
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
11561165
// Pull the cnums and name,vers,hash out of cstore
@@ -1298,7 +1307,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
12981307
None => LazySeq::empty(),
12991308
}
13001309
}
1310+
}
13011311

1312+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13021313
fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
13031314
let mut i = self.position();
13041315
let crate_deps = self.encode_crate_deps();
@@ -1448,6 +1459,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14481459
lazy_state: LazyState::NoNode,
14491460
type_shorthands: Default::default(),
14501461
predicate_shorthands: Default::default(),
1462+
metadata_hashes: Vec::new(),
14511463
};
14521464

14531465
// Encode the rustc version string in a predictable location.

‎src/librustc_metadata/index_builder.rs

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,19 @@ use encoder::EncodeContext;
5959
use index::Index;
6060
use schema::*;
6161

62-
use rustc::dep_graph::DepNode;
6362
use rustc::hir;
6463
use rustc::hir::def_id::DefId;
64+
use rustc::ich::{StableHashingContext, Fingerprint};
6565
use rustc::ty::TyCtxt;
6666
use syntax::ast;
6767

6868
use std::ops::{Deref, DerefMut};
6969

70+
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
71+
use rustc_serialize::Encodable;
72+
73+
use rustc::dep_graph::DepNode;
74+
7075
/// Builder that can encode new items, adding them into the index.
7176
/// Item encoding cannot be nested.
7277
pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
@@ -112,16 +117,29 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
112117
/// holds, and that it is therefore not gaining "secret" access to
113118
/// bits of HIR or other state that would not be trackd by the
114119
/// content system.
115-
pub fn record<DATA>(&mut self,
116-
id: DefId,
117-
op: fn(&mut EncodeContext<'b, 'tcx>, DATA) -> Entry<'tcx>,
118-
data: DATA)
120+
pub fn record<'x, DATA>(&'x mut self,
121+
id: DefId,
122+
op: fn(&mut EntryBuilder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
123+
data: DATA)
119124
where DATA: DepGraphRead
120125
{
121126
let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
122127
data.read(self.tcx);
123-
let entry = op(&mut self.ecx, data);
124-
self.items.record(id, self.ecx.lazy(&entry));
128+
129+
assert!(id.is_local());
130+
let tcx: TyCtxt<'b, 'tcx, 'tcx> = self.ecx.tcx;
131+
let ecx: &'x mut EncodeContext<'b, 'tcx> = &mut *self.ecx;
132+
let mut entry_builder = EntryBuilder {
133+
tcx: tcx,
134+
ecx: ecx,
135+
hasher: StableHasher::new(),
136+
hcx: StableHashingContext::new(tcx),
137+
};
138+
139+
let entry = op(&mut entry_builder, data);
140+
let entry = entry_builder.ecx.lazy(&entry);
141+
entry_builder.finish(id);
142+
self.items.record(id, entry);
125143
}
126144

127145
pub fn into_items(self) -> Index {
@@ -223,3 +241,48 @@ impl<T> DepGraphRead for FromId<T> {
223241
tcx.hir.read(self.0);
224242
}
225243
}
244+
245+
pub struct EntryBuilder<'a, 'b: 'a, 'tcx: 'b> {
246+
pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
247+
ecx: &'a mut EncodeContext<'b, 'tcx>,
248+
hasher: StableHasher<Fingerprint>,
249+
hcx: StableHashingContext<'b, 'tcx>,
250+
}
251+
252+
impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
253+
254+
pub fn finish(self, def_id: DefId) {
255+
let hash = self.hasher.finish();
256+
self.ecx.metadata_hashes.push((def_id.index, hash));
257+
}
258+
259+
pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
260+
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
261+
{
262+
value.hash_stable(&mut self.hcx, &mut self.hasher);
263+
self.ecx.lazy(value)
264+
}
265+
266+
pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
267+
where I: IntoIterator<Item = T>,
268+
T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
269+
{
270+
let items: Vec<T> = iter.into_iter().collect();
271+
items.hash_stable(&mut self.hcx, &mut self.hasher);
272+
self.ecx.lazy_seq(items)
273+
}
274+
275+
pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
276+
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
277+
{
278+
slice.hash_stable(&mut self.hcx, &mut self.hasher);
279+
self.ecx.lazy_seq_ref(slice.iter())
280+
}
281+
282+
pub fn lazy_seq_ref_from_slice<T>(&mut self, slice: &[&T]) -> LazySeq<T>
283+
where T: Encodable + HashStable<StableHashingContext<'b, 'tcx>>
284+
{
285+
slice.hash_stable(&mut self.hcx, &mut self.hasher);
286+
self.ecx.lazy_seq_ref(slice.iter().map(|x| *x))
287+
}
288+
}

‎src/librustc_metadata/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#![feature(rustc_private)]
2828
#![feature(specialization)]
2929
#![feature(staged_api)]
30+
#![feature(discriminant_value)]
3031

3132
#[macro_use]
3233
extern crate log;

‎src/librustc_metadata/schema.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ use syntax_pos::{self, Span};
2828

2929
use std::marker::PhantomData;
3030

31+
use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
32+
StableHasherResult};
33+
3134
pub fn rustc_version() -> String {
3235
format!("rustc {}",
3336
option_env!("CFG_VERSION").unwrap_or("unknown version"))
@@ -100,6 +103,15 @@ impl<T> Clone for Lazy<T> {
100103
impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
101104
impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
102105

106+
impl<CTX, T> HashStable<CTX> for Lazy<T> {
107+
fn hash_stable<W: StableHasherResult>(&self,
108+
_: &mut CTX,
109+
_: &mut StableHasher<W>) {
110+
// There's nothing to do. Whatever got encoded within this Lazy<>
111+
// wrapper has already been hashed.
112+
}
113+
}
114+
103115
/// A sequence of type T referred to by its absolute position
104116
/// in the metadata and length, and which can be decoded lazily.
105117
/// The sequence is a single node for the purposes of `Lazy`.
@@ -148,6 +160,15 @@ impl<T> Clone for LazySeq<T> {
148160
impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
149161
impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
150162

163+
impl<CTX, T> HashStable<CTX> for LazySeq<T> {
164+
fn hash_stable<W: StableHasherResult>(&self,
165+
_: &mut CTX,
166+
_: &mut StableHasher<W>) {
167+
// There's nothing to do. Whatever got encoded within this Lazy<>
168+
// wrapper has already been hashed.
169+
}
170+
}
171+
151172
/// Encoding / decoding state for `Lazy` and `LazySeq`.
152173
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
153174
pub enum LazyState {
@@ -251,17 +272,23 @@ pub struct ModData {
251272
pub reexports: LazySeq<def::Export>,
252273
}
253274

275+
impl_stable_hash_for!(struct ModData { reexports });
276+
254277
#[derive(RustcEncodable, RustcDecodable)]
255278
pub struct MacroDef {
256279
pub body: String,
257280
}
258281

282+
impl_stable_hash_for!(struct MacroDef { body });
283+
259284
#[derive(RustcEncodable, RustcDecodable)]
260285
pub struct FnData {
261286
pub constness: hir::Constness,
262287
pub arg_names: LazySeq<ast::Name>,
263288
}
264289

290+
impl_stable_hash_for!(struct FnData { constness, arg_names });
291+
265292
#[derive(RustcEncodable, RustcDecodable)]
266293
pub struct VariantData<'tcx> {
267294
pub ctor_kind: CtorKind,
@@ -273,6 +300,13 @@ pub struct VariantData<'tcx> {
273300
pub struct_ctor: Option<DefIndex>,
274301
}
275302

303+
impl_stable_hash_for!(struct VariantData<'tcx> {
304+
ctor_kind,
305+
discr,
306+
evaluated_discr,
307+
struct_ctor
308+
});
309+
276310
#[derive(RustcEncodable, RustcDecodable)]
277311
pub struct TraitData<'tcx> {
278312
pub unsafety: hir::Unsafety,
@@ -281,6 +315,13 @@ pub struct TraitData<'tcx> {
281315
pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
282316
}
283317

318+
impl_stable_hash_for!(struct TraitData<'tcx> {
319+
unsafety,
320+
paren_sugar,
321+
has_default_impl,
322+
super_predicates
323+
});
324+
284325
#[derive(RustcEncodable, RustcDecodable)]
285326
pub struct ImplData<'tcx> {
286327
pub polarity: hir::ImplPolarity,
@@ -291,6 +332,14 @@ pub struct ImplData<'tcx> {
291332
pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
292333
}
293334

335+
impl_stable_hash_for!(struct ImplData<'tcx> {
336+
polarity,
337+
parent_impl,
338+
coerce_unsized_info,
339+
trait_ref
340+
});
341+
342+
294343
/// Describes whether the container of an associated item
295344
/// is a trait or an impl and whether, in a trait, it has
296345
/// a default, or an in impl, whether it's marked "default".
@@ -302,6 +351,13 @@ pub enum AssociatedContainer {
302351
ImplFinal,
303352
}
304353

354+
impl_stable_hash_for!(enum ::schema::AssociatedContainer {
355+
TraitRequired,
356+
TraitWithDefault,
357+
ImplDefault,
358+
ImplFinal
359+
});
360+
305361
impl AssociatedContainer {
306362
pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
307363
match *self {
@@ -335,9 +391,11 @@ pub struct MethodData {
335391
pub container: AssociatedContainer,
336392
pub has_self: bool,
337393
}
394+
impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
338395

339396
#[derive(RustcEncodable, RustcDecodable)]
340397
pub struct ClosureData<'tcx> {
341398
pub kind: ty::ClosureKind,
342399
pub ty: Lazy<ty::PolyFnSig<'tcx>>,
343400
}
401+
impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });

0 commit comments

Comments
 (0)
Please sign in to comment.