Skip to content

Commit 06f1099

Browse files
alexcrichtonbrson
authored andcommitted
rustc: More fixes for arch-independent hashing
In another attempt to fix #36793 this commit attempts to head off any future problems by adding a custom `WidentUsizeHasher` which will widen any hashing of `isize` and `usize` to a `u64` as necessary. This obviates the need for a previous number of `as u64` annotations and will hopefully protect us against future problems here. Closes #36793 (hopefully)
1 parent 64d498a commit 06f1099

File tree

2 files changed

+73
-8
lines changed

2 files changed

+73
-8
lines changed

src/librustc/ty/util.rs

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use hir::def_id::DefId;
1414
use infer::InferCtxt;
15+
use hir::map as ast_map;
1516
use hir::pat_util;
1617
use traits::{self, Reveal};
1718
use 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+
392454
pub struct TypeIdHasher<'a, 'gcx: 'a+'tcx, 'tcx: 'a, H> {
393455
tcx: TyCtxt<'a, 'gcx, 'tcx>,
394-
state: H
456+
state: WidenUsizeHasher<H>,
395457
}
396458

397459
impl<'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

src/librustc_trans/back/symbol_names.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,17 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
152152
let mut hash_state = scx.symbol_hasher().borrow_mut();
153153
record_time(&tcx.sess.perf_stats.symbol_hash_time, || {
154154
hash_state.reset();
155-
let mut hasher = Sha256Hasher(&mut hash_state);
155+
let hasher = Sha256Hasher(&mut hash_state);
156+
let mut hasher = ty::util::TypeIdHasher::new(tcx, hasher);
156157

157158
// the main symbol name is not necessarily unique; hash in the
158159
// compiler's internal def-path, guaranteeing each symbol has a
159160
// truly unique path
160-
def_path.deterministic_hash_to(tcx, &mut hasher);
161+
hasher.def_path(def_path);
161162

162163
// Include the main item-type. Note that, in this case, the
163164
// assertions about `needs_subst` may not hold, but this item-type
164165
// ought to be the same for every reference anyway.
165-
let mut hasher = ty::util::TypeIdHasher::new(tcx, hasher);
166166
assert!(!item_type.has_erasable_regions());
167167
hasher.visit_ty(item_type);
168168

0 commit comments

Comments
 (0)