1use std::{
2 hash::{BuildHasher, Hash, Hasher},
3 mem,
4};
5
6use siphasher::sip128::{Hash128, Hasher128, SipHasher24};
7
8pub struct StableHasher {
16 state: SipHasher24,
17}
18
19impl ::std::fmt::Debug for StableHasher {
20 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
21 write!(f, "{:?}", self.state)
22 }
23}
24
25pub trait StableHasherResult: Sized {
26 fn finish(hasher: StableHasher) -> Self;
27}
28
29impl StableHasher {
30 #[inline]
31 pub fn new() -> Self {
32 StableHasher {
33 state: SipHasher24::new_with_keys(0, 0),
34 }
35 }
36
37 #[inline]
38 pub fn finish<W: StableHasherResult>(self) -> W {
39 W::finish(self)
40 }
41}
42
43impl StableHasherResult for u128 {
44 #[inline]
45 fn finish(hasher: StableHasher) -> Self {
46 hasher.finalize().as_u128()
47 }
48}
49
50impl StableHasherResult for u64 {
51 #[inline]
52 fn finish(hasher: StableHasher) -> Self {
53 hasher.finalize().h1
54 }
55}
56
57impl StableHasher {
58 #[inline]
59 pub fn finalize(self) -> Hash128 {
60 self.state.finish128()
61 }
62}
63
64impl Hasher for StableHasher {
65 fn finish(&self) -> u64 {
66 panic!("use StableHasher::finalize instead");
67 }
68
69 #[inline]
70 fn write(&mut self, bytes: &[u8]) {
71 self.state.write(bytes);
72 }
73
74 #[inline]
75 fn write_u8(&mut self, i: u8) {
76 self.state.write_u8(i);
77 }
78
79 #[inline]
80 fn write_u16(&mut self, i: u16) {
81 self.state.write_u16(i.to_le());
82 }
83
84 #[inline]
85 fn write_u32(&mut self, i: u32) {
86 self.state.write_u32(i.to_le());
87 }
88
89 #[inline]
90 fn write_u64(&mut self, i: u64) {
91 self.state.write_u64(i.to_le());
92 }
93
94 #[inline]
95 fn write_u128(&mut self, i: u128) {
96 self.state.write_u128(i.to_le());
97 }
98
99 #[inline]
100 fn write_usize(&mut self, i: usize) {
101 self.state.write_u64((i as u64).to_le());
105 }
106
107 #[inline]
108 fn write_i8(&mut self, i: i8) {
109 self.state.write_i8(i);
110 }
111
112 #[inline]
113 fn write_i16(&mut self, i: i16) {
114 self.state.write_i16(i.to_le());
115 }
116
117 #[inline]
118 fn write_i32(&mut self, i: i32) {
119 self.state.write_i32(i.to_le());
120 }
121
122 #[inline]
123 fn write_i64(&mut self, i: i64) {
124 self.state.write_i64(i.to_le());
125 }
126
127 #[inline]
128 fn write_i128(&mut self, i: i128) {
129 self.state.write_i128(i.to_le());
130 }
131
132 #[inline]
133 fn write_isize(&mut self, i: isize) {
134 let value = i as u64;
140
141 #[cold]
143 #[inline(never)]
144 fn hash_value(state: &mut SipHasher24, value: u64) {
145 state.write_u8(0xff);
146 state.write_u64(value.to_le());
147 }
148
149 if value < 0xff {
165 self.state.write_u8(value as u8);
166 } else {
167 hash_value(&mut self.state, value);
168 }
169 }
170}
171
172pub trait HashStable<CTX> {
175 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher);
176}
177
178pub trait ToStableHashKey<HCX> {
182 type KeyType: Ord + Clone + Sized + HashStable<HCX>;
183 fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
184}
185
186#[macro_export]
189macro_rules! impl_stable_hash_via_hash {
190 ($t:ty) => {
191 impl<CTX> $crate::rustc_data_structures::stable_hasher::HashStable<CTX> for $t {
192 #[inline]
193 fn hash_stable(
194 &self,
195 _: &mut CTX,
196 hasher: &mut $crate::rustc_data_structures::stable_hasher::StableHasher,
197 ) {
198 ::std::hash::Hash::hash(self, hasher);
199 }
200 }
201 };
202}
203
204impl_stable_hash_via_hash!(i8);
205impl_stable_hash_via_hash!(i16);
206impl_stable_hash_via_hash!(i32);
207impl_stable_hash_via_hash!(i64);
208impl_stable_hash_via_hash!(isize);
209
210impl_stable_hash_via_hash!(u8);
211impl_stable_hash_via_hash!(u16);
212impl_stable_hash_via_hash!(u32);
213impl_stable_hash_via_hash!(u64);
214impl_stable_hash_via_hash!(usize);
215
216impl_stable_hash_via_hash!(u128);
217impl_stable_hash_via_hash!(i128);
218
219impl_stable_hash_via_hash!(char);
220impl_stable_hash_via_hash!(());
221
222impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
223 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
224 self.get().hash_stable(ctx, hasher)
225 }
226}
227
228impl<CTX> HashStable<CTX> for f32 {
229 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
230 let val: u32 = unsafe { ::std::mem::transmute(*self) };
231 val.hash_stable(ctx, hasher);
232 }
233}
234
235impl<CTX> HashStable<CTX> for f64 {
236 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
237 let val: u64 = unsafe { ::std::mem::transmute(*self) };
238 val.hash_stable(ctx, hasher);
239 }
240}
241
242impl<CTX> HashStable<CTX> for ::std::cmp::Ordering {
243 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
244 (*self as i8).hash_stable(ctx, hasher);
245 }
246}
247
248impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
249 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
250 let (ref _0,) = *self;
251 _0.hash_stable(ctx, hasher);
252 }
253}
254
255impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2) {
256 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
257 let (ref _0, ref _1) = *self;
258 _0.hash_stable(ctx, hasher);
259 _1.hash_stable(ctx, hasher);
260 }
261}
262
263impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
264where
265 T1: HashStable<CTX>,
266 T2: HashStable<CTX>,
267 T3: HashStable<CTX>,
268{
269 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
270 let (ref _0, ref _1, ref _2) = *self;
271 _0.hash_stable(ctx, hasher);
272 _1.hash_stable(ctx, hasher);
273 _2.hash_stable(ctx, hasher);
274 }
275}
276
277impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
278where
279 T1: HashStable<CTX>,
280 T2: HashStable<CTX>,
281 T3: HashStable<CTX>,
282 T4: HashStable<CTX>,
283{
284 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
285 let (ref _0, ref _1, ref _2, ref _3) = *self;
286 _0.hash_stable(ctx, hasher);
287 _1.hash_stable(ctx, hasher);
288 _2.hash_stable(ctx, hasher);
289 _3.hash_stable(ctx, hasher);
290 }
291}
292
293impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
294 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
295 self.len().hash_stable(ctx, hasher);
296 for item in self {
297 item.hash_stable(ctx, hasher);
298 }
299 }
300}
301
302impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
303 #[inline]
304 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
305 (&self[..]).hash_stable(ctx, hasher);
306 }
307}
308
309impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
310 #[inline]
311 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
312 (**self).hash_stable(ctx, hasher);
313 }
314}
315
316impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
317 #[inline]
318 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
319 (**self).hash_stable(ctx, hasher);
320 }
321}
322
323impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> {
324 #[inline]
325 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
326 (**self).hash_stable(ctx, hasher);
327 }
328}
329
330impl<CTX> HashStable<CTX> for str {
331 #[inline]
332 fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
333 self.len().hash(hasher);
334 self.as_bytes().hash(hasher);
335 }
336}
337
338impl<CTX> HashStable<CTX> for String {
339 #[inline]
340 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
341 (&self[..]).hash_stable(hcx, hasher);
342 }
343}
344
345impl<HCX> ToStableHashKey<HCX> for String {
346 type KeyType = String;
347
348 #[inline]
349 fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
350 self.clone()
351 }
352}
353
354impl<CTX> HashStable<CTX> for bool {
355 #[inline]
356 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
357 (if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher);
358 }
359}
360
361impl<T, CTX> HashStable<CTX> for Option<T>
362where
363 T: HashStable<CTX>,
364{
365 #[inline]
366 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
367 if let Some(ref value) = *self {
368 1u8.hash_stable(ctx, hasher);
369 value.hash_stable(ctx, hasher);
370 } else {
371 0u8.hash_stable(ctx, hasher);
372 }
373 }
374}
375
376impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
377where
378 T1: HashStable<CTX>,
379 T2: HashStable<CTX>,
380{
381 #[inline]
382 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
383 mem::discriminant(self).hash_stable(ctx, hasher);
384 match *self {
385 Ok(ref x) => x.hash_stable(ctx, hasher),
386 Err(ref x) => x.hash_stable(ctx, hasher),
387 }
388 }
389}
390
391impl<'a, T, CTX> HashStable<CTX> for &'a T
392where
393 T: HashStable<CTX> + ?Sized,
394{
395 #[inline]
396 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
397 (**self).hash_stable(ctx, hasher);
398 }
399}
400
401impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
402 #[inline]
403 fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
404 ::std::hash::Hash::hash(self, hasher);
405 }
406}
407
408impl_stable_hash_via_hash!(::std::path::Path);
427impl_stable_hash_via_hash!(::std::path::PathBuf);
428
429impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
430where
431 K: ToStableHashKey<HCX> + Eq,
432 V: HashStable<HCX>,
433 R: BuildHasher,
434{
435 #[inline]
436 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
437 stable_hash_reduce(
438 hcx,
439 hasher,
440 self.iter(),
441 self.len(),
442 |hasher, hcx, (key, value)| {
443 let key = key.to_stable_hash_key(hcx);
444 key.hash_stable(hcx, hasher);
445 value.hash_stable(hcx, hasher);
446 },
447 );
448 }
449}
450
451impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R>
452where
453 K: ToStableHashKey<HCX> + Eq,
454 R: BuildHasher,
455{
456 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
457 stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
458 let key = key.to_stable_hash_key(hcx);
459 key.hash_stable(hcx, hasher);
460 });
461 }
462}
463
464impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
465where
466 K: ToStableHashKey<HCX>,
467 V: HashStable<HCX>,
468{
469 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
470 stable_hash_reduce(
471 hcx,
472 hasher,
473 self.iter(),
474 self.len(),
475 |hasher, hcx, (key, value)| {
476 let key = key.to_stable_hash_key(hcx);
477 key.hash_stable(hcx, hasher);
478 value.hash_stable(hcx, hasher);
479 },
480 );
481 }
482}
483
484impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
485where
486 K: ToStableHashKey<HCX>,
487{
488 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
489 stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
490 let key = key.to_stable_hash_key(hcx);
491 key.hash_stable(hcx, hasher);
492 });
493 }
494}
495
496fn stable_hash_reduce<HCX, I, C, F>(
497 hcx: &mut HCX,
498 hasher: &mut StableHasher,
499 mut collection: C,
500 length: usize,
501 hash_function: F,
502) where
503 C: Iterator<Item = I>,
504 F: Fn(&mut StableHasher, &mut HCX, I),
505{
506 length.hash_stable(hcx, hasher);
507
508 match length {
509 1 => {
510 hash_function(hasher, hcx, collection.next().unwrap());
511 }
512 _ => {
513 let hash = collection
514 .map(|value| {
515 let mut hasher = StableHasher::new();
516 hash_function(&mut hasher, hcx, value);
517 hasher.finish::<u128>()
518 })
519 .reduce(|accum, value| accum.wrapping_add(value));
520 hash.hash_stable(hcx, hasher);
521 }
522 }
523}