1212
1313use hir:: def_id:: DefId ;
1414use infer:: InferCtxt ;
15+ use hir:: map as ast_map;
1516use hir:: pat_util;
1617use traits:: { self , Reveal } ;
1718use ty:: { self , Ty , AdtKind , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
@@ -389,16 +390,77 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
389390 }
390391}
391392
393+ // When hashing a type this ends up affecting properties like symbol names. We
394+ // want these symbol names to be calculated independent of other factors like
395+ // what architecture you're compiling *from*.
396+ //
397+ // The hashing just uses the standard `Hash` trait, but the implementations of
398+ // `Hash` for the `usize` and `isize` types are *not* architecture independent
399+ // (e.g. they has 4 or 8 bytes). As a result we want to avoid `usize` and
400+ // `isize` completely when hashing. To ensure that these don't leak in we use a
401+ // custom hasher implementation here which inflates the size of these to a `u64`
402+ // and `i64`.
403+ struct WidenUsizeHasher < H > {
404+ inner : H ,
405+ }
406+
407+ impl < H > WidenUsizeHasher < H > {
408+ fn new ( inner : H ) -> WidenUsizeHasher < H > {
409+ WidenUsizeHasher { inner : inner }
410+ }
411+ }
412+
413+ impl < H : Hasher > Hasher for WidenUsizeHasher < H > {
414+ fn write ( & mut self , bytes : & [ u8 ] ) {
415+ self . inner . write ( bytes)
416+ }
417+
418+ fn finish ( & self ) -> u64 {
419+ self . inner . finish ( )
420+ }
421+
422+ fn write_u8 ( & mut self , i : u8 ) {
423+ self . inner . write_u8 ( i)
424+ }
425+ fn write_u16 ( & mut self , i : u16 ) {
426+ self . inner . write_u16 ( i)
427+ }
428+ fn write_u32 ( & mut self , i : u32 ) {
429+ self . inner . write_u32 ( i)
430+ }
431+ fn write_u64 ( & mut self , i : u64 ) {
432+ self . inner . write_u64 ( i)
433+ }
434+ fn write_usize ( & mut self , i : usize ) {
435+ self . inner . write_u64 ( i as u64 )
436+ }
437+ fn write_i8 ( & mut self , i : i8 ) {
438+ self . inner . write_i8 ( i)
439+ }
440+ fn write_i16 ( & mut self , i : i16 ) {
441+ self . inner . write_i16 ( i)
442+ }
443+ fn write_i32 ( & mut self , i : i32 ) {
444+ self . inner . write_i32 ( i)
445+ }
446+ fn write_i64 ( & mut self , i : i64 ) {
447+ self . inner . write_i64 ( i)
448+ }
449+ fn write_isize ( & mut self , i : isize ) {
450+ self . inner . write_i64 ( i as i64 )
451+ }
452+ }
453+
392454pub struct TypeIdHasher < ' a , ' gcx : ' a +' tcx , ' tcx : ' a , H > {
393455 tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
394- state : H
456+ state : WidenUsizeHasher < H > ,
395457}
396458
397459impl < ' a , ' gcx , ' tcx , H : Hasher > TypeIdHasher < ' a , ' gcx , ' tcx , H > {
398460 pub fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , state : H ) -> Self {
399461 TypeIdHasher {
400462 tcx : tcx,
401- state : state
463+ state : WidenUsizeHasher :: new ( state) ,
402464 }
403465 }
404466
@@ -422,9 +484,12 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> {
422484 fn def_id ( & mut self , did : DefId ) {
423485 // Hash the DefPath corresponding to the DefId, which is independent
424486 // of compiler internal state.
425- let tcx = self . tcx ;
426- let def_path = tcx. def_path ( did) ;
427- def_path. deterministic_hash_to ( tcx, & mut self . state ) ;
487+ let path = self . tcx . def_path ( did) ;
488+ self . def_path ( & path)
489+ }
490+
491+ pub fn def_path ( & mut self , def_path : & ast_map:: DefPath ) {
492+ def_path. deterministic_hash_to ( self . tcx , & mut self . state ) ;
428493 }
429494}
430495
0 commit comments