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 } ;
@@ -388,16 +389,77 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
388389 }
389390}
390391
392+ // When hashing a type this ends up affecting properties like symbol names. We
393+ // want these symbol names to be calculated independent of other factors like
394+ // what architecture you're compiling *from*.
395+ //
396+ // The hashing just uses the standard `Hash` trait, but the implementations of
397+ // `Hash` for the `usize` and `isize` types are *not* architecture independent
398+ // (e.g. they has 4 or 8 bytes). As a result we want to avoid `usize` and
399+ // `isize` completely when hashing. To ensure that these don't leak in we use a
400+ // custom hasher implementation here which inflates the size of these to a `u64`
401+ // and `i64`.
402+ struct WidenUsizeHasher < H > {
403+ inner : H ,
404+ }
405+
406+ impl < H > WidenUsizeHasher < H > {
407+ fn new ( inner : H ) -> WidenUsizeHasher < H > {
408+ WidenUsizeHasher { inner : inner }
409+ }
410+ }
411+
412+ impl < H : Hasher > Hasher for WidenUsizeHasher < H > {
413+ fn write ( & mut self , bytes : & [ u8 ] ) {
414+ self . inner . write ( bytes)
415+ }
416+
417+ fn finish ( & self ) -> u64 {
418+ self . inner . finish ( )
419+ }
420+
421+ fn write_u8 ( & mut self , i : u8 ) {
422+ self . inner . write_u8 ( i)
423+ }
424+ fn write_u16 ( & mut self , i : u16 ) {
425+ self . inner . write_u16 ( i)
426+ }
427+ fn write_u32 ( & mut self , i : u32 ) {
428+ self . inner . write_u32 ( i)
429+ }
430+ fn write_u64 ( & mut self , i : u64 ) {
431+ self . inner . write_u64 ( i)
432+ }
433+ fn write_usize ( & mut self , i : usize ) {
434+ self . inner . write_u64 ( i as u64 )
435+ }
436+ fn write_i8 ( & mut self , i : i8 ) {
437+ self . inner . write_i8 ( i)
438+ }
439+ fn write_i16 ( & mut self , i : i16 ) {
440+ self . inner . write_i16 ( i)
441+ }
442+ fn write_i32 ( & mut self , i : i32 ) {
443+ self . inner . write_i32 ( i)
444+ }
445+ fn write_i64 ( & mut self , i : i64 ) {
446+ self . inner . write_i64 ( i)
447+ }
448+ fn write_isize ( & mut self , i : isize ) {
449+ self . inner . write_i64 ( i as i64 )
450+ }
451+ }
452+
391453pub struct TypeIdHasher < ' a , ' gcx : ' a +' tcx , ' tcx : ' a , H > {
392454 tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
393- state : H
455+ state : WidenUsizeHasher < H > ,
394456}
395457
396458impl < ' a , ' gcx , ' tcx , H : Hasher > TypeIdHasher < ' a , ' gcx , ' tcx , H > {
397459 pub fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , state : H ) -> Self {
398460 TypeIdHasher {
399461 tcx : tcx,
400- state : state
462+ state : WidenUsizeHasher :: new ( state) ,
401463 }
402464 }
403465
@@ -421,9 +483,12 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> {
421483 fn def_id ( & mut self , did : DefId ) {
422484 // Hash the DefPath corresponding to the DefId, which is independent
423485 // of compiler internal state.
424- let tcx = self . tcx ;
425- let def_path = tcx. def_path ( did) ;
426- def_path. deterministic_hash_to ( tcx, & mut self . state ) ;
486+ let path = self . tcx . def_path ( did) ;
487+ self . def_path ( & path)
488+ }
489+
490+ pub fn def_path ( & mut self , def_path : & ast_map:: DefPath ) {
491+ def_path. deterministic_hash_to ( self . tcx , & mut self . state ) ;
427492 }
428493}
429494
@@ -436,7 +501,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
436501 TyInt ( i) => self . hash ( i) ,
437502 TyUint ( u) => self . hash ( u) ,
438503 TyFloat ( f) => self . hash ( f) ,
439- TyArray ( _, n) => self . hash ( n as u64 ) ,
504+ TyArray ( _, n) => self . hash ( n) ,
440505 TyRawPtr ( m) |
441506 TyRef ( _, m) => self . hash ( m. mutbl ) ,
442507 TyClosure ( def_id, _) |
@@ -447,14 +512,14 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
447512 self . hash ( f. unsafety ) ;
448513 self . hash ( f. abi ) ;
449514 self . hash ( f. sig . variadic ( ) ) ;
450- self . hash ( f. sig . inputs ( ) . skip_binder ( ) . len ( ) as u64 ) ;
515+ self . hash ( f. sig . inputs ( ) . skip_binder ( ) . len ( ) ) ;
451516 }
452517 TyTrait ( ref data) => {
453518 self . def_id ( data. principal . def_id ( ) ) ;
454519 self . hash ( data. builtin_bounds ) ;
455520 }
456521 TyTuple ( tys) => {
457- self . hash ( tys. len ( ) as u64 ) ;
522+ self . hash ( tys. len ( ) ) ;
458523 }
459524 TyParam ( p) => {
460525 self . hash ( p. idx ) ;
0 commit comments