1use std::hash::{BuildHasher, Hash, Hasher};
2use std::marker::PhantomData;
3use std::mem;
4use std::num::NonZero;
5
6use rustc_index::bit_set::{self, DenseBitSet};
7use rustc_index::{Idx, IndexSlice, IndexVec};
8use smallvec::SmallVec;
9
10#[cfg(test)]
11mod tests;
12
13pub use rustc_stable_hash::{
14 FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
15};
16
17pub use crate::hashes::{Hash64, Hash128};
18
19pub trait HashStable<CTX> {
46 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher);
47}
48
49pub trait ToStableHashKey<HCX> {
53 type KeyType: Ord + Sized + HashStable<HCX>;
54 fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType;
55}
56
57pub trait StableOrd: Ord {
87 const CAN_USE_UNSTABLE_SORT: bool;
88
89 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: ();
92}
93
94impl<T: StableOrd> StableOrd for &T {
95 const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
96
97 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
101}
102
103pub trait StableCompare {
114 const CAN_USE_UNSTABLE_SORT: bool;
115
116 fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering;
117}
118
119impl<T: StableOrd> StableCompare for T {
122 const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
123
124 fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering {
125 self.cmp(other)
126 }
127}
128
129macro_rules! impl_stable_traits_for_trivial_type {
139 ($t:ty) => {
140 impl<CTX> $crate::stable_hasher::HashStable<CTX> for $t {
141 #[inline]
142 fn hash_stable(&self, _: &mut CTX, hasher: &mut $crate::stable_hasher::StableHasher) {
143 ::std::hash::Hash::hash(self, hasher);
144 }
145 }
146
147 impl $crate::stable_hasher::StableOrd for $t {
148 const CAN_USE_UNSTABLE_SORT: bool = true;
149
150 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
153 }
154 };
155}
156
157pub(crate) use impl_stable_traits_for_trivial_type;
158
159impl_stable_traits_for_trivial_type!(i8);
160impl_stable_traits_for_trivial_type!(i16);
161impl_stable_traits_for_trivial_type!(i32);
162impl_stable_traits_for_trivial_type!(i64);
163impl_stable_traits_for_trivial_type!(isize);
164
165impl_stable_traits_for_trivial_type!(u8);
166impl_stable_traits_for_trivial_type!(u16);
167impl_stable_traits_for_trivial_type!(u32);
168impl_stable_traits_for_trivial_type!(u64);
169impl_stable_traits_for_trivial_type!(usize);
170
171impl_stable_traits_for_trivial_type!(u128);
172impl_stable_traits_for_trivial_type!(i128);
173
174impl_stable_traits_for_trivial_type!(char);
175impl_stable_traits_for_trivial_type!(());
176
177impl_stable_traits_for_trivial_type!(Hash64);
178
179impl<CTX> HashStable<CTX> for Hash128 {
182 #[inline]
183 fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
184 self.as_u128().hash(hasher);
185 }
186}
187
188impl StableOrd for Hash128 {
189 const CAN_USE_UNSTABLE_SORT: bool = true;
190
191 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
194}
195
196impl<CTX> HashStable<CTX> for ! {
197 fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
198 unreachable!()
199 }
200}
201
202impl<CTX, T> HashStable<CTX> for PhantomData<T> {
203 fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {}
204}
205
206impl<CTX> HashStable<CTX> for NonZero<u32> {
207 #[inline]
208 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
209 self.get().hash_stable(ctx, hasher)
210 }
211}
212
213impl<CTX> HashStable<CTX> for NonZero<usize> {
214 #[inline]
215 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
216 self.get().hash_stable(ctx, hasher)
217 }
218}
219
220impl<CTX> HashStable<CTX> for f32 {
221 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
222 let val: u32 = self.to_bits();
223 val.hash_stable(ctx, hasher);
224 }
225}
226
227impl<CTX> HashStable<CTX> for f64 {
228 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
229 let val: u64 = self.to_bits();
230 val.hash_stable(ctx, hasher);
231 }
232}
233
234impl<CTX> HashStable<CTX> for ::std::cmp::Ordering {
235 #[inline]
236 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
237 (*self as i8).hash_stable(ctx, hasher);
238 }
239}
240
241impl<T1: HashStable<CTX>, CTX> HashStable<CTX> for (T1,) {
242 #[inline]
243 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
244 let (ref _0,) = *self;
245 _0.hash_stable(ctx, hasher);
246 }
247}
248
249impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2) {
250 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
251 let (ref _0, ref _1) = *self;
252 _0.hash_stable(ctx, hasher);
253 _1.hash_stable(ctx, hasher);
254 }
255}
256
257impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
258 const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT;
259
260 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
263}
264
265impl<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
266where
267 T1: HashStable<CTX>,
268 T2: HashStable<CTX>,
269 T3: HashStable<CTX>,
270{
271 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
272 let (ref _0, ref _1, ref _2) = *self;
273 _0.hash_stable(ctx, hasher);
274 _1.hash_stable(ctx, hasher);
275 _2.hash_stable(ctx, hasher);
276 }
277}
278
279impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
280 const CAN_USE_UNSTABLE_SORT: bool =
281 T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
282
283 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
286}
287
288impl<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
289where
290 T1: HashStable<CTX>,
291 T2: HashStable<CTX>,
292 T3: HashStable<CTX>,
293 T4: HashStable<CTX>,
294{
295 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
296 let (ref _0, ref _1, ref _2, ref _3) = *self;
297 _0.hash_stable(ctx, hasher);
298 _1.hash_stable(ctx, hasher);
299 _2.hash_stable(ctx, hasher);
300 _3.hash_stable(ctx, hasher);
301 }
302}
303
304impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
305 const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
306 && T2::CAN_USE_UNSTABLE_SORT
307 && T3::CAN_USE_UNSTABLE_SORT
308 && T4::CAN_USE_UNSTABLE_SORT;
309
310 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
313}
314
315impl<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
316 default fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
317 self.len().hash_stable(ctx, hasher);
318 for item in self {
319 item.hash_stable(ctx, hasher);
320 }
321 }
322}
323
324impl<CTX> HashStable<CTX> for [u8] {
325 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
326 self.len().hash_stable(ctx, hasher);
327 hasher.write(self);
328 }
329}
330
331impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
332 #[inline]
333 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
334 self[..].hash_stable(ctx, hasher);
335 }
336}
337
338impl<K, V, R, CTX> HashStable<CTX> for indexmap::IndexMap<K, V, R>
339where
340 K: HashStable<CTX> + Eq + Hash,
341 V: HashStable<CTX>,
342 R: BuildHasher,
343{
344 #[inline]
345 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
346 self.len().hash_stable(ctx, hasher);
347 for kv in self {
348 kv.hash_stable(ctx, hasher);
349 }
350 }
351}
352
353impl<K, R, CTX> HashStable<CTX> for indexmap::IndexSet<K, R>
354where
355 K: HashStable<CTX> + Eq + Hash,
356 R: BuildHasher,
357{
358 #[inline]
359 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
360 self.len().hash_stable(ctx, hasher);
361 for key in self {
362 key.hash_stable(ctx, hasher);
363 }
364 }
365}
366
367impl<A, const N: usize, CTX> HashStable<CTX> for SmallVec<[A; N]>
368where
369 A: HashStable<CTX>,
370{
371 #[inline]
372 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
373 self[..].hash_stable(ctx, hasher);
374 }
375}
376
377impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
378 #[inline]
379 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
380 (**self).hash_stable(ctx, hasher);
381 }
382}
383
384impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
385 #[inline]
386 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
387 (**self).hash_stable(ctx, hasher);
388 }
389}
390
391impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> {
392 #[inline]
393 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
394 (**self).hash_stable(ctx, hasher);
395 }
396}
397
398impl<CTX> HashStable<CTX> for str {
399 #[inline]
400 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
401 self.as_bytes().hash_stable(ctx, hasher);
402 }
403}
404
405impl StableOrd for &str {
406 const CAN_USE_UNSTABLE_SORT: bool = true;
407
408 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
411}
412
413impl<CTX> HashStable<CTX> for String {
414 #[inline]
415 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
416 self[..].hash_stable(hcx, hasher);
417 }
418}
419
420impl StableOrd for String {
421 const CAN_USE_UNSTABLE_SORT: bool = true;
422
423 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
426}
427
428impl<HCX> ToStableHashKey<HCX> for String {
429 type KeyType = String;
430 #[inline]
431 fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
432 self.clone()
433 }
434}
435
436impl<HCX, T1: ToStableHashKey<HCX>, T2: ToStableHashKey<HCX>> ToStableHashKey<HCX> for (T1, T2) {
437 type KeyType = (T1::KeyType, T2::KeyType);
438 #[inline]
439 fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType {
440 (self.0.to_stable_hash_key(hcx), self.1.to_stable_hash_key(hcx))
441 }
442}
443
444impl<CTX> HashStable<CTX> for bool {
445 #[inline]
446 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
447 (if *self { 1u8 } else { 0u8 }).hash_stable(ctx, hasher);
448 }
449}
450
451impl StableOrd for bool {
452 const CAN_USE_UNSTABLE_SORT: bool = true;
453
454 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
456}
457
458impl<T, CTX> HashStable<CTX> for Option<T>
459where
460 T: HashStable<CTX>,
461{
462 #[inline]
463 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
464 if let Some(ref value) = *self {
465 1u8.hash_stable(ctx, hasher);
466 value.hash_stable(ctx, hasher);
467 } else {
468 0u8.hash_stable(ctx, hasher);
469 }
470 }
471}
472
473impl<T: StableOrd> StableOrd for Option<T> {
474 const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
475
476 const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
478}
479
480impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
481where
482 T1: HashStable<CTX>,
483 T2: HashStable<CTX>,
484{
485 #[inline]
486 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
487 mem::discriminant(self).hash_stable(ctx, hasher);
488 match *self {
489 Ok(ref x) => x.hash_stable(ctx, hasher),
490 Err(ref x) => x.hash_stable(ctx, hasher),
491 }
492 }
493}
494
495impl<'a, T, CTX> HashStable<CTX> for &'a T
496where
497 T: HashStable<CTX> + ?Sized,
498{
499 #[inline]
500 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
501 (**self).hash_stable(ctx, hasher);
502 }
503}
504
505impl<T, CTX> HashStable<CTX> for ::std::mem::Discriminant<T> {
506 #[inline]
507 fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
508 ::std::hash::Hash::hash(self, hasher);
509 }
510}
511
512impl<T, CTX> HashStable<CTX> for ::std::ops::RangeInclusive<T>
513where
514 T: HashStable<CTX>,
515{
516 #[inline]
517 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
518 self.start().hash_stable(ctx, hasher);
519 self.end().hash_stable(ctx, hasher);
520 }
521}
522
523impl<I: Idx, T, CTX> HashStable<CTX> for IndexSlice<I, T>
524where
525 T: HashStable<CTX>,
526{
527 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
528 self.len().hash_stable(ctx, hasher);
529 for v in &self.raw {
530 v.hash_stable(ctx, hasher);
531 }
532 }
533}
534
535impl<I: Idx, T, CTX> HashStable<CTX> for IndexVec<I, T>
536where
537 T: HashStable<CTX>,
538{
539 fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
540 self.len().hash_stable(ctx, hasher);
541 for v in &self.raw {
542 v.hash_stable(ctx, hasher);
543 }
544 }
545}
546
547impl<I: Idx, CTX> HashStable<CTX> for DenseBitSet<I> {
548 fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) {
549 ::std::hash::Hash::hash(self, hasher);
550 }
551}
552
553impl<R: Idx, C: Idx, CTX> HashStable<CTX> for bit_set::BitMatrix<R, C> {
554 fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) {
555 ::std::hash::Hash::hash(self, hasher);
556 }
557}
558
559impl<T, CTX> HashStable<CTX> for bit_set::FiniteBitSet<T>
560where
561 T: HashStable<CTX> + bit_set::FiniteBitSetTy,
562{
563 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
564 self.0.hash_stable(hcx, hasher);
565 }
566}
567
568impl_stable_traits_for_trivial_type!(::std::path::Path);
569impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
570
571impl<V, HCX> !HashStable<HCX> for std::collections::HashSet<V> {}
575impl<K, V, HCX> !HashStable<HCX> for std::collections::HashMap<K, V> {}
576
577impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
578where
579 K: HashStable<HCX> + StableOrd,
580 V: HashStable<HCX>,
581{
582 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
583 self.len().hash_stable(hcx, hasher);
584 for entry in self.iter() {
585 entry.hash_stable(hcx, hasher);
586 }
587 }
588}
589
590impl<K, HCX> HashStable<HCX> for ::std::collections::BTreeSet<K>
591where
592 K: HashStable<HCX> + StableOrd,
593{
594 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
595 self.len().hash_stable(hcx, hasher);
596 for entry in self.iter() {
597 entry.hash_stable(hcx, hasher);
598 }
599 }
600}
601
602#[derive(Clone, Hash, Eq, PartialEq, Debug)]
610pub struct HashingControls {
611 pub hash_spans: bool,
612}