12
12
13
13
use hir:: def_id:: DefId ;
14
14
use infer:: InferCtxt ;
15
+ use hir:: map as ast_map;
15
16
use hir:: pat_util;
16
17
use traits:: { self , Reveal } ;
17
18
use ty:: { self , Ty , AdtKind , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
@@ -389,16 +390,77 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
389
390
}
390
391
}
391
392
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
+
392
454
pub struct TypeIdHasher < ' a , ' gcx : ' a +' tcx , ' tcx : ' a , H > {
393
455
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
394
- state : H
456
+ state : WidenUsizeHasher < H > ,
395
457
}
396
458
397
459
impl < ' a , ' gcx , ' tcx , H : Hasher > TypeIdHasher < ' a , ' gcx , ' tcx , H > {
398
460
pub fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , state : H ) -> Self {
399
461
TypeIdHasher {
400
462
tcx : tcx,
401
- state : state
463
+ state : WidenUsizeHasher :: new ( state) ,
402
464
}
403
465
}
404
466
@@ -422,9 +484,12 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeIdHasher<'a, 'gcx, 'tcx, H> {
422
484
fn def_id ( & mut self , did : DefId ) {
423
485
// Hash the DefPath corresponding to the DefId, which is independent
424
486
// 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 ) ;
428
493
}
429
494
}
430
495
0 commit comments