Skip to main content

rustc_data_structures/
stable_hash.rs

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;
9use thin_vec::ThinVec;
10
11use crate::fingerprint::Fingerprint;
12
13#[cfg(test)]
14mod tests;
15
16use rustc_hashes::{Hash64, Hash128};
17pub use rustc_stable_hash::{
18    FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
19};
20
21/// This trait lets `StableHash` and `derive(StableHash)` be used in
22/// this crate (and other crates upstream of `rustc_middle`), while leaving
23/// certain operations to be defined in `rustc_middle` where more things are
24/// visible.
25pub trait StableHashCtxt {
26    /// The main event: stable hashing of a span.
27    fn stable_hash_span(&mut self, span: RawSpan, hasher: &mut StableHasher);
28
29    /// Compute a `Fingerprint`, which can be trivially turned into a `DefPathHash`.
30    fn def_path_hash(&self, def_id: RawDefId) -> Fingerprint;
31
32    /// Get the stable hash controls.
33    fn stable_hash_controls(&self) -> StableHashControls;
34
35    /// Assert that the provided `StableHashCtxt` is configured with the default
36    /// `StableHashControls`. We should always have bailed out before getting to here with a
37    fn assert_default_stable_hash_controls(&self, msg: &str);
38}
39
40// A type used to work around `Span` not being visible in this crate. It is the same layout as
41// `Span`.
42pub struct RawSpan(pub u32, pub u16, pub u16);
43
44// A type used to work around `DefId` not being visible in this crate. It is the same size as
45// `DefId`.
46pub struct RawDefId(pub u32, pub u32);
47
48/// Something that implements `StableHash` can be hashed in a way that is
49/// stable across multiple compilation sessions.
50///
51/// Note that `StableHash` imposes rather more strict requirements than usual
52/// hash functions:
53///
54/// - Stable hashes are sometimes used as identifiers. Therefore they must
55///   conform to the corresponding `PartialEq` implementations:
56///
57///     - `x == y` implies `stable_hash(x) == stable_hash(y)`, and
58///     - `x != y` implies `stable_hash(x) != stable_hash(y)`.
59///
60///   That second condition is usually not required for hash functions
61///   (e.g. `Hash`). In practice this means that `stable_hash` must feed any
62///   information into the hasher that a `PartialEq` comparison takes into
63///   account. See [#49300](https://github.com/rust-lang/rust/issues/49300)
64///   for an example where violating this invariant has caused trouble in the
65///   past.
66///
67/// - `stable_hash()` must be independent of the current
68///    compilation session. E.g. they must not hash memory addresses or other
69///    things that are "randomly" assigned per compilation session.
70///
71/// - `stable_hash()` must be independent of the host architecture. The
72///   `StableHasher` takes care of endianness and `isize`/`usize` platform
73///   differences.
74pub trait StableHash {
75    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher);
76}
77
78/// Implement this for types that can be turned into stable keys like, for
79/// example, for DefId that can be converted to a DefPathHash. This is used for
80/// bringing maps into a predictable order before hashing them.
81pub trait ToStableHashKey {
82    type KeyType: Ord + Sized + StableHash;
83    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> Self::KeyType;
84}
85
86/// Trait for marking a type as having a sort order that is
87/// stable across compilation session boundaries. More formally:
88///
89/// ```txt
90/// Ord::cmp(a1, b1) == Ord::cmp(a2, b2)
91///    where a2 = decode(encode(a1, context1), context2)
92///          b2 = decode(encode(b1, context1), context2)
93/// ```
94///
95/// i.e. the result of `Ord::cmp` is not influenced by encoding
96/// the values in one session and then decoding them in another
97/// session.
98///
99/// This is trivially true for types where encoding and decoding
100/// don't change the bytes of the values that are used during
101/// comparison and comparison only depends on these bytes (as
102/// opposed to some non-local state). Examples are u32, String,
103/// Path, etc.
104///
105/// But it is not true for:
106///  - `*const T` and `*mut T` because the values of these pointers
107///    will change between sessions.
108///  - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
109///    values depend on state that might be different between
110///    compilation sessions.
111///
112/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
113/// unstable sorting can be used for this type. Set to true if and
114/// only if `a == b` implies `a` and `b` are fully indistinguishable.
115pub trait StableOrd: Ord {
116    const CAN_USE_UNSTABLE_SORT: bool;
117
118    /// Marker to ensure that implementors have carefully considered
119    /// whether their `Ord` implementation obeys this trait's contract.
120    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: ();
121}
122
123impl<T: StableOrd> StableOrd for &T {
124    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
125
126    // Ordering of a reference is exactly that of the referent, and since
127    // the ordering of the referet is stable so must be the ordering of the
128    // reference.
129    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
130}
131
132/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
133/// compared in a cross-session stable way, but their `Ord` implementation is
134/// not stable. In such cases, a `StableOrd` implementation can be provided
135/// to offer a lightweight way for stable sorting. (The more heavyweight option
136/// is to sort via `ToStableHashKey`, but then sorting needs to have access to
137/// a stable hashing context and `ToStableHashKey` can also be expensive as in
138/// the case of `Symbol` where it has to allocate a `String`.)
139///
140/// See the documentation of [StableOrd] for how stable sort order is defined.
141/// The same definition applies here. Be careful when implementing this trait.
142pub trait StableCompare {
143    const CAN_USE_UNSTABLE_SORT: bool;
144
145    fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering;
146}
147
148/// `StableOrd` denotes that the type's `Ord` implementation is stable, so
149/// we can implement `StableCompare` by just delegating to `Ord`.
150impl<T: StableOrd> StableCompare for T {
151    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
152
153    fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering {
154        self.cmp(other)
155    }
156}
157
158/// Implement StableHash by just calling `Hash::hash()`. Also implement `StableOrd` for the type
159/// since that has the same requirements.
160///
161/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
162/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
163/// for examples). Therefore this macro is not exported and should only be used in the limited cases
164/// here in this module.
165///
166/// Use `#[derive(StableHash)]` instead.
167macro_rules! impl_stable_traits_for_trivial_type {
168    ($t:ty) => {
169        impl $crate::stable_hash::StableHash for $t {
170            #[inline]
171            fn stable_hash<Hcx>(
172                &self,
173                _: &mut Hcx,
174                hasher: &mut $crate::stable_hash::StableHasher,
175            ) {
176                ::std::hash::Hash::hash(self, hasher);
177            }
178        }
179
180        impl $crate::stable_hash::StableOrd for $t {
181            const CAN_USE_UNSTABLE_SORT: bool = true;
182
183            // Encoding and decoding doesn't change the bytes of trivial types
184            // and `Ord::cmp` depends only on those bytes.
185            const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
186        }
187    };
188}
189
190pub(crate) use impl_stable_traits_for_trivial_type;
191
192impl crate::stable_hash::StableHash for i8 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for i8 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(i8);
193impl crate::stable_hash::StableHash for i16 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for i16 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(i16);
194impl crate::stable_hash::StableHash for i32 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for i32 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(i32);
195impl crate::stable_hash::StableHash for i64 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for i64 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(i64);
196impl crate::stable_hash::StableHash for isize {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for isize {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(isize);
197
198impl crate::stable_hash::StableHash for u8 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for u8 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(u8);
199impl crate::stable_hash::StableHash for u16 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for u16 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(u16);
200impl crate::stable_hash::StableHash for u32 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for u32 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(u32);
201impl crate::stable_hash::StableHash for u64 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for u64 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(u64);
202impl crate::stable_hash::StableHash for usize {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for usize {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(usize);
203
204impl crate::stable_hash::StableHash for u128 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for u128 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(u128);
205impl crate::stable_hash::StableHash for i128 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for i128 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(i128);
206
207impl crate::stable_hash::StableHash for char {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for char {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(char);
208impl crate::stable_hash::StableHash for () {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for () {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(());
209
210impl crate::stable_hash::StableHash for Hash64 {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for Hash64 {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(Hash64);
211
212// We need a custom impl as the default hash function will only hash half the bits. For stable
213// hashing we want to hash the full 128-bit hash.
214impl StableHash for Hash128 {
215    #[inline]
216    fn stable_hash<Hcx>(&self, _: &mut Hcx, hasher: &mut StableHasher) {
217        self.as_u128().hash(hasher);
218    }
219}
220
221impl StableOrd for Hash128 {
222    const CAN_USE_UNSTABLE_SORT: bool = true;
223
224    // Encoding and decoding doesn't change the bytes of `Hash128`
225    // and `Ord::cmp` depends only on those bytes.
226    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
227}
228
229impl StableHash for ! {
230    fn stable_hash<Hcx>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {
231        ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
232    }
233}
234
235impl<T> StableHash for PhantomData<T> {
236    fn stable_hash<Hcx>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {}
237}
238
239impl<T: StableHash + std::num::ZeroablePrimitive> StableHash for NonZero<T> {
240    #[inline]
241    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
242        self.get().stable_hash(hcx, hasher)
243    }
244}
245
246impl StableHash for f32 {
247    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
248        let val: u32 = self.to_bits();
249        val.stable_hash(hcx, hasher);
250    }
251}
252
253impl StableHash for f64 {
254    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
255        let val: u64 = self.to_bits();
256        val.stable_hash(hcx, hasher);
257    }
258}
259
260impl StableHash for ::std::cmp::Ordering {
261    #[inline]
262    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
263        (*self as i8).stable_hash(hcx, hasher);
264    }
265}
266
267impl<T1: StableHash> StableHash for (T1,) {
268    #[inline]
269    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
270        let (ref _0,) = *self;
271        _0.stable_hash(hcx, hasher);
272    }
273}
274
275impl<T1: StableHash, T2: StableHash> StableHash for (T1, T2) {
276    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
277        let (ref _0, ref _1) = *self;
278        _0.stable_hash(hcx, hasher);
279        _1.stable_hash(hcx, hasher);
280    }
281}
282
283impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
284    const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT;
285
286    // Ordering of tuples is a pure function of their elements' ordering, and since
287    // the ordering of each element is stable so must be the ordering of the tuple.
288    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
289}
290
291impl<T1, T2, T3> StableHash for (T1, T2, T3)
292where
293    T1: StableHash,
294    T2: StableHash,
295    T3: StableHash,
296{
297    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
298        let (ref _0, ref _1, ref _2) = *self;
299        _0.stable_hash(hcx, hasher);
300        _1.stable_hash(hcx, hasher);
301        _2.stable_hash(hcx, hasher);
302    }
303}
304
305impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
306    const CAN_USE_UNSTABLE_SORT: bool =
307        T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
308
309    // Ordering of tuples is a pure function of their elements' ordering, and since
310    // the ordering of each element is stable so must be the ordering of the tuple.
311    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
312}
313
314impl<T1, T2, T3, T4> StableHash for (T1, T2, T3, T4)
315where
316    T1: StableHash,
317    T2: StableHash,
318    T3: StableHash,
319    T4: StableHash,
320{
321    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
322        let (ref _0, ref _1, ref _2, ref _3) = *self;
323        _0.stable_hash(hcx, hasher);
324        _1.stable_hash(hcx, hasher);
325        _2.stable_hash(hcx, hasher);
326        _3.stable_hash(hcx, hasher);
327    }
328}
329
330impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
331    const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
332        && T2::CAN_USE_UNSTABLE_SORT
333        && T3::CAN_USE_UNSTABLE_SORT
334        && T4::CAN_USE_UNSTABLE_SORT;
335
336    // Ordering of tuples is a pure function of their elements' ordering, and since
337    // the ordering of each element is stable so must be the ordering of the tuple.
338    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
339}
340
341impl<T: StableHash> StableHash for [T] {
342    default fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
343        self.len().stable_hash(hcx, hasher);
344        for item in self {
345            item.stable_hash(hcx, hasher);
346        }
347    }
348}
349
350impl StableHash for [u8] {
351    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
352        self.len().stable_hash(hcx, hasher);
353        hasher.write(self);
354    }
355}
356
357impl<T: StableHash> StableHash for Vec<T> {
358    #[inline]
359    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
360        self[..].stable_hash(hcx, hasher);
361    }
362}
363
364impl<K, V, R> StableHash for indexmap::IndexMap<K, V, R>
365where
366    K: StableHash + Eq + Hash,
367    V: StableHash,
368    R: BuildHasher,
369{
370    #[inline]
371    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
372        self.len().stable_hash(hcx, hasher);
373        for kv in self {
374            kv.stable_hash(hcx, hasher);
375        }
376    }
377}
378
379impl<K, R> StableHash for indexmap::IndexSet<K, R>
380where
381    K: StableHash + Eq + Hash,
382    R: BuildHasher,
383{
384    #[inline]
385    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
386        self.len().stable_hash(hcx, hasher);
387        for key in self {
388            key.stable_hash(hcx, hasher);
389        }
390    }
391}
392
393impl<A, const N: usize> StableHash for SmallVec<[A; N]>
394where
395    A: StableHash,
396{
397    #[inline]
398    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
399        self[..].stable_hash(hcx, hasher);
400    }
401}
402
403impl<T: StableHash> StableHash for ThinVec<T> {
404    #[inline]
405    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
406        self[..].stable_hash(hcx, hasher);
407    }
408}
409
410impl<T: ?Sized + StableHash> StableHash for Box<T> {
411    #[inline]
412    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
413        (**self).stable_hash(hcx, hasher);
414    }
415}
416
417impl<T: ?Sized + StableHash> StableHash for ::std::rc::Rc<T> {
418    #[inline]
419    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
420        (**self).stable_hash(hcx, hasher);
421    }
422}
423
424impl<T: ?Sized + StableHash> StableHash for ::std::sync::Arc<T> {
425    #[inline]
426    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
427        (**self).stable_hash(hcx, hasher);
428    }
429}
430
431impl StableHash for str {
432    #[inline]
433    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
434        self.as_bytes().stable_hash(hcx, hasher);
435    }
436}
437
438impl StableOrd for &str {
439    const CAN_USE_UNSTABLE_SORT: bool = true;
440
441    // Encoding and decoding doesn't change the bytes of string slices
442    // and `Ord::cmp` depends only on those bytes.
443    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
444}
445
446impl StableHash for String {
447    #[inline]
448    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
449        self[..].stable_hash(hcx, hasher);
450    }
451}
452
453impl StableOrd for String {
454    const CAN_USE_UNSTABLE_SORT: bool = true;
455
456    // String comparison only depends on their contents and the
457    // contents are not changed by (de-)serialization.
458    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
459}
460
461impl StableHash for bool {
462    #[inline]
463    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
464        (if *self { 1u8 } else { 0u8 }).stable_hash(hcx, hasher);
465    }
466}
467
468impl StableOrd for bool {
469    const CAN_USE_UNSTABLE_SORT: bool = true;
470
471    // sort order of bools is not changed by (de-)serialization.
472    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
473}
474
475impl<T> StableHash for Option<T>
476where
477    T: StableHash,
478{
479    #[inline]
480    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
481        if let Some(ref value) = *self {
482            1u8.stable_hash(hcx, hasher);
483            value.stable_hash(hcx, hasher);
484        } else {
485            0u8.stable_hash(hcx, hasher);
486        }
487    }
488}
489
490impl<T: StableOrd> StableOrd for Option<T> {
491    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
492
493    // the Option wrapper does not add instability to comparison.
494    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
495}
496
497impl<T1, T2> StableHash for Result<T1, T2>
498where
499    T1: StableHash,
500    T2: StableHash,
501{
502    #[inline]
503    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
504        mem::discriminant(self).stable_hash(hcx, hasher);
505        match *self {
506            Ok(ref x) => x.stable_hash(hcx, hasher),
507            Err(ref x) => x.stable_hash(hcx, hasher),
508        }
509    }
510}
511
512impl<'a, T> StableHash for &'a T
513where
514    T: StableHash + ?Sized,
515{
516    #[inline]
517    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
518        (**self).stable_hash(hcx, hasher);
519    }
520}
521
522impl<T> StableHash for ::std::mem::Discriminant<T> {
523    #[inline]
524    fn stable_hash<Hcx: StableHashCtxt>(&self, _: &mut Hcx, hasher: &mut StableHasher) {
525        ::std::hash::Hash::hash(self, hasher);
526    }
527}
528
529impl<T> StableHash for ::std::range::RangeInclusive<T>
530where
531    T: StableHash,
532{
533    #[inline]
534    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
535        self.start.stable_hash(hcx, hasher);
536        self.last.stable_hash(hcx, hasher);
537    }
538}
539
540impl<I: Idx, T> StableHash for IndexSlice<I, T>
541where
542    T: StableHash,
543{
544    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
545        self.len().stable_hash(hcx, hasher);
546        for v in &self.raw {
547            v.stable_hash(hcx, hasher);
548        }
549    }
550}
551
552impl<I: Idx, T> StableHash for IndexVec<I, T>
553where
554    T: StableHash,
555{
556    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
557        self.len().stable_hash(hcx, hasher);
558        for v in &self.raw {
559            v.stable_hash(hcx, hasher);
560        }
561    }
562}
563
564impl<I: Idx> StableHash for DenseBitSet<I> {
565    fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, hasher: &mut StableHasher) {
566        ::std::hash::Hash::hash(self, hasher);
567    }
568}
569
570impl<R: Idx, C: Idx> StableHash for bit_set::BitMatrix<R, C> {
571    fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, hasher: &mut StableHasher) {
572        ::std::hash::Hash::hash(self, hasher);
573    }
574}
575
576impl crate::stable_hash::StableHash for ::std::ffi::OsStr {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for ::std::ffi::OsStr {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(::std::ffi::OsStr);
577
578impl crate::stable_hash::StableHash for ::std::path::Path {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for ::std::path::Path {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(::std::path::Path);
579impl crate::stable_hash::StableHash for ::std::path::PathBuf {
    #[inline]
    fn stable_hash<Hcx>(&self, _: &mut Hcx,
        hasher: &mut crate::stable_hash::StableHasher) {
        ::std::hash::Hash::hash(self, hasher);
    }
}
impl crate::stable_hash::StableOrd for ::std::path::PathBuf {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}impl_stable_traits_for_trivial_type!(::std::path::PathBuf);
580
581// It is not safe to implement StableHash for HashSet, HashMap or any other collection type
582// with unstable but observable iteration order.
583// See https://github.com/rust-lang/compiler-team/issues/533 for further information.
584impl<V> !StableHash for std::collections::HashSet<V> {}
585impl<K, V> !StableHash for std::collections::HashMap<K, V> {}
586
587impl<K, V> StableHash for ::std::collections::BTreeMap<K, V>
588where
589    K: StableHash + StableOrd,
590    V: StableHash,
591{
592    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
593        self.len().stable_hash(hcx, hasher);
594        for entry in self.iter() {
595            entry.stable_hash(hcx, hasher);
596        }
597    }
598}
599
600impl<K> StableHash for ::std::collections::BTreeSet<K>
601where
602    K: StableHash + StableOrd,
603{
604    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
605        self.len().stable_hash(hcx, hasher);
606        for entry in self.iter() {
607            entry.stable_hash(hcx, hasher);
608        }
609    }
610}
611
612/// Controls what data we do or do not hash.
613/// Whenever a `StableHash` implementation caches its
614/// result, it needs to include `StableHashControls` as part
615/// of the key, to ensure that it does not produce an incorrect
616/// result (for example, using a `Fingerprint` produced while
617/// hashing `Span`s when a `Fingerprint` without `Span`s is
618/// being requested)
619#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for StableHashControls { }
#[automatically_derived]
impl ::core::clone::Clone for StableHashControls {
    #[inline]
    fn clone(&self) -> StableHashControls {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for StableHashControls { }Copy, #[automatically_derived]
impl ::core::hash::Hash for StableHashControls {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.hash_spans, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::Eq for StableHashControls {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for StableHashControls { }
#[automatically_derived]
impl ::core::cmp::PartialEq for StableHashControls {
    #[inline]
    fn eq(&self, other: &StableHashControls) -> bool {
        self.hash_spans == other.hash_spans
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for StableHashControls {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "StableHashControls", "hash_spans", &&self.hash_spans)
    }
}Debug)]
620pub struct StableHashControls {
621    pub hash_spans: bool,
622}