Skip to content

Commit 0445fbd

Browse files
committed
Store hashes in special types so they aren't accidentally encoded as numbers
1 parent de96f3d commit 0445fbd

File tree

38 files changed

+274
-138
lines changed

38 files changed

+274
-138
lines changed

compiler/rustc_abi/src/layout.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ pub trait LayoutCalculator {
7979
{
8080
// `ReprOptions.layout_seed` is a deterministic seed that we can use to
8181
// randomize field ordering with
82-
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
82+
let mut rng =
83+
Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64());
8384

8485
// Shuffle the ordering of the fields
8586
optimizing.shuffle(&mut rng);

compiler/rustc_abi/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::str::FromStr;
99

1010
use bitflags::bitflags;
1111
use rustc_data_structures::intern::Interned;
12+
use rustc_data_structures::stable_hasher::Hash64;
1213
#[cfg(feature = "nightly")]
1314
use rustc_data_structures::stable_hasher::StableOrd;
1415
use rustc_index::vec::{IndexSlice, IndexVec};
@@ -77,12 +78,12 @@ pub struct ReprOptions {
7778
pub flags: ReprFlags,
7879
/// The seed to be used for randomizing a type's layout
7980
///
80-
/// Note: This could technically be a `[u8; 16]` (a `u128`) which would
81+
/// Note: This could technically be a `Hash128` which would
8182
/// be the "most accurate" hash as it'd encompass the item and crate
8283
/// hash without loss, but it does pay the price of being larger.
83-
/// Everything's a tradeoff, a `u64` seed should be sufficient for our
84+
/// Everything's a tradeoff, a 64-bit seed should be sufficient for our
8485
/// purposes (primarily `-Z randomize-layout`)
85-
pub field_shuffle_seed: u64,
86+
pub field_shuffle_seed: Hash64,
8687
}
8788

8889
impl ReprOptions {

compiler/rustc_codegen_llvm/src/common.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::value::Value;
1010
use rustc_ast::Mutability;
1111
use rustc_codegen_ssa::mir::place::PlaceRef;
1212
use rustc_codegen_ssa::traits::*;
13-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13+
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
1414
use rustc_hir::def_id::DefId;
1515
use rustc_middle::bug;
1616
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@@ -261,7 +261,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
261261
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
262262
let mut hasher = StableHasher::new();
263263
alloc.hash_stable(&mut hcx, &mut hasher);
264-
hasher.finish::<u128>()
264+
hasher.finish::<Hash128>()
265265
});
266266
llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
267267
}

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_codegen_ssa::debuginfo::type_names;
2121
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
2222
use rustc_codegen_ssa::traits::*;
2323
use rustc_data_structures::fx::FxHashMap;
24+
use rustc_data_structures::stable_hasher::Hash128;
2425
use rustc_data_structures::sync::Lrc;
2526
use rustc_hir::def_id::{DefId, DefIdMap};
2627
use rustc_index::vec::IndexVec;
@@ -61,7 +62,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> {
6162
llcontext: &'ll llvm::Context,
6263
llmod: &'ll llvm::Module,
6364
builder: &'ll mut DIBuilder<'ll>,
64-
created_files: RefCell<FxHashMap<Option<(u128, SourceFileHash)>, &'ll DIFile>>,
65+
created_files: RefCell<FxHashMap<Option<(Hash128, SourceFileHash)>, &'ll DIFile>>,
6566

6667
type_map: metadata::TypeMap<'ll, 'tcx>,
6768
namespace_map: RefCell<DefIdMap<&'ll DIScope>>,

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// * `"` is treated as the start of a string.
1313

1414
use rustc_data_structures::fx::FxHashSet;
15-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
15+
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
1616
use rustc_hir::def_id::DefId;
1717
use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
1818
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability};
@@ -675,8 +675,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
675675
hcx.while_hashing_spans(false, |hcx| {
676676
ct.to_valtree().hash_stable(hcx, &mut hasher)
677677
});
678-
let hash: u64 = hasher.finish();
679-
hash
678+
hasher.finish::<Hash64>()
680679
});
681680

682681
if cpp_like_debuginfo(tcx) {

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
7575
}
7676
sym::type_id => {
7777
ensure_monomorphic_enough(tcx, tp_ty)?;
78-
ConstValue::from_u64(tcx.type_id_hash(tp_ty))
78+
ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
7979
}
8080
sym::variant_count => match tp_ty.kind() {
8181
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.

compiler/rustc_data_structures/src/fingerprint.rs

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::stable_hasher;
1+
use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
22
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
33
use std::hash::{Hash, Hasher};
44

@@ -9,32 +9,47 @@ mod tests;
99
#[repr(C)]
1010
pub struct Fingerprint(u64, u64);
1111

12-
impl Fingerprint {
13-
pub const ZERO: Fingerprint = Fingerprint(0, 0);
12+
pub trait FingerprintComponent {
13+
fn as_u64(&self) -> u64;
14+
}
1415

15-
#[inline]
16-
pub fn new(_0: u64, _1: u64) -> Fingerprint {
17-
Fingerprint(_0, _1)
16+
impl FingerprintComponent for Hash64 {
17+
fn as_u64(&self) -> u64 {
18+
Hash64::as_u64(*self)
19+
}
20+
}
21+
22+
impl FingerprintComponent for u64 {
23+
fn as_u64(&self) -> u64 {
24+
*self
1825
}
26+
}
27+
28+
impl Fingerprint {
29+
pub const ZERO: Fingerprint = Fingerprint(0, 0);
1930

2031
#[inline]
21-
pub fn from_smaller_hash(hash: u64) -> Fingerprint {
22-
Fingerprint(hash, hash)
32+
pub fn new<A, B>(_0: A, _1: B) -> Fingerprint
33+
where
34+
A: FingerprintComponent,
35+
B: FingerprintComponent,
36+
{
37+
Fingerprint(_0.as_u64(), _1.as_u64())
2338
}
2439

2540
#[inline]
26-
pub fn to_smaller_hash(&self) -> u64 {
41+
pub fn to_smaller_hash(&self) -> Hash64 {
2742
// Even though both halves of the fingerprint are expected to be good
2843
// quality hash values, let's still combine the two values because the
2944
// Fingerprints in DefPathHash have the StableCrateId portion which is
3045
// the same for all DefPathHashes from the same crate. Combining the
3146
// two halves makes sure we get a good quality hash in such cases too.
32-
self.0.wrapping_mul(3).wrapping_add(self.1)
47+
Hash64::new(self.0.wrapping_mul(3).wrapping_add(self.1))
3348
}
3449

3550
#[inline]
36-
pub fn as_value(&self) -> (u64, u64) {
37-
(self.0, self.1)
51+
pub fn split(&self) -> (Hash64, Hash64) {
52+
(Hash64::new(self.0), Hash64::new(self.1))
3853
}
3954

4055
#[inline]
@@ -131,9 +146,9 @@ impl FingerprintHasher for crate::unhash::Unhasher {
131146
}
132147
}
133148

134-
impl stable_hasher::StableHasherResult for Fingerprint {
149+
impl StableHasherResult for Fingerprint {
135150
#[inline]
136-
fn finish(hasher: stable_hasher::StableHasher) -> Self {
151+
fn finish(hasher: StableHasher) -> Self {
137152
let (_0, _1) = hasher.finalize();
138153
Fingerprint(_0, _1)
139154
}

compiler/rustc_data_structures/src/fingerprint/tests.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use super::*;
2+
use crate::stable_hasher::Hash64;
23

34
// Check that `combine_commutative` is order independent.
45
#[test]
56
fn combine_commutative_is_order_independent() {
6-
let a = Fingerprint::new(0xf6622fb349898b06, 0x70be9377b2f9c610);
7-
let b = Fingerprint::new(0xa9562bf5a2a5303c, 0x67d9b6c82034f13d);
8-
let c = Fingerprint::new(0x0d013a27811dbbc3, 0x9a3f7b3d9142ec43);
7+
let a = Fingerprint::new(Hash64::new(0xf6622fb349898b06), Hash64::new(0x70be9377b2f9c610));
8+
let b = Fingerprint::new(Hash64::new(0xa9562bf5a2a5303c), Hash64::new(0x67d9b6c82034f13d));
9+
let c = Fingerprint::new(Hash64::new(0x0d013a27811dbbc3), Hash64::new(0x9a3f7b3d9142ec43));
910
let permutations = [(a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), (c, b, a)];
1011
let f = a.combine_commutative(b).combine_commutative(c);
1112
for p in &permutations {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
2+
use std::fmt;
3+
use std::ops::BitXorAssign;
4+
use crate::stable_hasher::{StableHasher, StableHasherResult};
5+
6+
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
7+
pub struct Hash64 {
8+
inner: u64,
9+
}
10+
11+
impl Hash64 {
12+
pub const ZERO: Hash64 = Hash64 { inner: 0 };
13+
14+
#[inline]
15+
pub(crate) fn new(n: u64) -> Self {
16+
Self { inner: n }
17+
}
18+
19+
#[inline]
20+
pub fn as_u64(self) -> u64 {
21+
self.inner
22+
}
23+
}
24+
25+
impl BitXorAssign<u64> for Hash64 {
26+
fn bitxor_assign(&mut self, rhs: u64) {
27+
self.inner ^= rhs;
28+
}
29+
}
30+
31+
impl<S: Encoder> Encodable<S> for Hash64 {
32+
#[inline]
33+
fn encode(&self, s: &mut S) {
34+
s.emit_raw_bytes(&self.inner.to_le_bytes());
35+
}
36+
}
37+
38+
impl<D: Decoder> Decodable<D> for Hash64 {
39+
#[inline]
40+
fn decode(d: &mut D) -> Self {
41+
Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) }
42+
}
43+
}
44+
45+
impl StableHasherResult for Hash64 {
46+
#[inline]
47+
fn finish(hasher: StableHasher) -> Self {
48+
Self { inner: hasher.finalize().0 }
49+
}
50+
}
51+
52+
impl fmt::Debug for Hash64 {
53+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54+
self.inner.fmt(f)
55+
}
56+
}
57+
58+
impl fmt::LowerHex for Hash64 {
59+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60+
fmt::LowerHex::fmt(&self.inner, f)
61+
}
62+
}
63+
64+
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
65+
pub struct Hash128 {
66+
inner: u128,
67+
}
68+
69+
impl Hash128 {
70+
#[inline]
71+
pub fn truncate(self) -> Hash64 {
72+
Hash64 { inner: self.inner as u64 }
73+
}
74+
75+
#[inline]
76+
pub fn wrapping_add(self, other: Self) -> Self {
77+
Self {
78+
inner: self.inner.wrapping_add(other.inner),
79+
}
80+
}
81+
82+
#[inline]
83+
pub fn as_u128(self) -> u128 {
84+
self.inner
85+
}
86+
}
87+
88+
impl<S: Encoder> Encodable<S> for Hash128 {
89+
#[inline]
90+
fn encode(&self, s: &mut S) {
91+
s.emit_raw_bytes(&self.inner.to_le_bytes());
92+
}
93+
}
94+
95+
impl<D: Decoder> Decodable<D> for Hash128 {
96+
#[inline]
97+
fn decode(d: &mut D) -> Self {
98+
Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) }
99+
}
100+
}
101+
102+
impl StableHasherResult for Hash128 {
103+
#[inline]
104+
fn finish(hasher: StableHasher) -> Self {
105+
let (_0, _1) = hasher.finalize();
106+
Self { inner: u128::from(_0) | (u128::from(_1) << 64) }
107+
}
108+
}
109+
110+
impl fmt::Debug for Hash128 {
111+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112+
self.inner.fmt(f)
113+
}
114+
}
115+
116+
impl fmt::LowerHex for Hash128 {
117+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118+
fmt::LowerHex::fmt(&self.inner, f)
119+
}
120+
}

compiler/rustc_data_structures/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub mod work_queue;
8686
pub use atomic_ref::AtomicRef;
8787
pub mod aligned;
8888
pub mod frozen;
89+
mod hashes;
8990
pub mod owned_slice;
9091
pub mod sso;
9192
pub mod steal;

compiler/rustc_data_structures/src/stable_hasher.rs

+9-18
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use crate::sip128::SipHasher128;
22
use rustc_index::bit_set;
33
use rustc_index::vec;
44
use smallvec::SmallVec;
5+
use std::fmt;
56
use std::hash::{BuildHasher, Hash, Hasher};
67
use std::marker::PhantomData;
78
use std::mem;
89

910
#[cfg(test)]
1011
mod tests;
1112

13+
pub use crate::hashes::{Hash128, Hash64};
14+
1215
/// When hashing something that ends up affecting properties like symbol names,
1316
/// we want these symbol names to be calculated independently of other factors
1417
/// like what architecture you're compiling *from*.
@@ -20,8 +23,8 @@ pub struct StableHasher {
2023
state: SipHasher128,
2124
}
2225

23-
impl ::std::fmt::Debug for StableHasher {
24-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26+
impl fmt::Debug for StableHasher {
27+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2528
write!(f, "{:?}", self.state)
2629
}
2730
}
@@ -42,21 +45,6 @@ impl StableHasher {
4245
}
4346
}
4447

45-
impl StableHasherResult for u128 {
46-
#[inline]
47-
fn finish(hasher: StableHasher) -> Self {
48-
let (_0, _1) = hasher.finalize();
49-
u128::from(_0) | (u128::from(_1) << 64)
50-
}
51-
}
52-
53-
impl StableHasherResult for u64 {
54-
#[inline]
55-
fn finish(hasher: StableHasher) -> Self {
56-
hasher.finalize().0
57-
}
58-
}
59-
6048
impl StableHasher {
6149
#[inline]
6250
pub fn finalize(self) -> (u64, u64) {
@@ -287,6 +275,9 @@ impl_stable_traits_for_trivial_type!(i128);
287275
impl_stable_traits_for_trivial_type!(char);
288276
impl_stable_traits_for_trivial_type!(());
289277

278+
impl_stable_traits_for_trivial_type!(Hash64);
279+
impl_stable_traits_for_trivial_type!(Hash128);
280+
290281
impl<CTX> HashStable<CTX> for ! {
291282
fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
292283
unreachable!()
@@ -669,7 +660,7 @@ fn stable_hash_reduce<HCX, I, C, F>(
669660
.map(|value| {
670661
let mut hasher = StableHasher::new();
671662
hash_function(&mut hasher, hcx, value);
672-
hasher.finish::<u128>()
663+
hasher.finish::<Hash128>()
673664
})
674665
.reduce(|accum, value| accum.wrapping_add(value));
675666
hash.hash_stable(hcx, hasher);

compiler/rustc_data_structures/src/stable_hasher/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn test_hash_isize() {
7272
assert_eq!(h.finalize(), expected);
7373
}
7474

75-
fn hash<T: HashStable<()>>(t: &T) -> u128 {
75+
fn hash<T: HashStable<()>>(t: &T) -> Hash128 {
7676
let mut h = StableHasher::new();
7777
let ctx = &mut ();
7878
t.hash_stable(ctx, &mut h);

0 commit comments

Comments
 (0)