Skip to main content

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