Skip to main content

rustc_data_structures/
stable_hash.rs

1use std::hash::{BuildHasher, Hash, Hasher};
2use std::marker::PhantomData;
3use std::num::NonZero;
4
5use rustc_index::bit_set::{self, DenseBitSet};
6use rustc_index::{Idx, IndexSlice, IndexVec};
7use rustc_macros::StableHash;
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/// Dummy impl of [`StableHashCtxt`], for code that can't provide a real context,
41/// and only wants to compute stable hashes for types that don't rely on the context.
42pub struct DummyStableHashCtxt;
43
44impl StableHashCtxt for DummyStableHashCtxt {
45    fn stable_hash_span(&mut self, _span: RawSpan, _hasher: &mut StableHasher) {
46        {
    ::core::panicking::panic_fmt(format_args!("method on dummy stable-hash context was unexpectedly called"));
};panic!("method on dummy stable-hash context was unexpectedly called");
47    }
48    fn def_path_hash(&self, _def_id: RawDefId) -> Fingerprint {
49        {
    ::core::panicking::panic_fmt(format_args!("method on dummy stable-hash context was unexpectedly called"));
};panic!("method on dummy stable-hash context was unexpectedly called");
50    }
51    fn stable_hash_controls(&self) -> StableHashControls {
52        {
    ::core::panicking::panic_fmt(format_args!("method on dummy stable-hash context was unexpectedly called"));
};panic!("method on dummy stable-hash context was unexpectedly called");
53    }
54    fn assert_default_stable_hash_controls(&self, _msg: &str) {
55        {
    ::core::panicking::panic_fmt(format_args!("method on dummy stable-hash context was unexpectedly called"));
};panic!("method on dummy stable-hash context was unexpectedly called");
56    }
57}
58
59// A type used to work around `Span` not being visible in this crate. It is the same size as
60// `Span` but has a different alignment.
61pub struct RawSpan(pub u64);
62
63// A type used to work around `DefId` not being visible in this crate. It is the same size as
64// `DefId`.
65pub struct RawDefId(pub u32, pub u32);
66
67/// Something that implements `StableHash` can be hashed in a way that is
68/// stable across multiple compilation sessions.
69///
70/// Note that `StableHash` imposes rather more strict requirements than usual
71/// hash functions:
72///
73/// - Stable hashes are sometimes used as identifiers. Therefore they must
74///   conform to the corresponding `PartialEq` implementations:
75///
76///     - `x == y` implies `stable_hash(x) == stable_hash(y)`, and
77///     - `x != y` implies `stable_hash(x) != stable_hash(y)`.
78///
79///   That second condition is usually not required for hash functions
80///   (e.g. `Hash`). In practice this means that `stable_hash` must feed any
81///   information into the hasher that a `PartialEq` comparison takes into
82///   account. See [#49300](https://github.com/rust-lang/rust/issues/49300)
83///   for an example where violating this invariant has caused trouble in the
84///   past.
85///
86/// - `stable_hash()` must be independent of the current
87///    compilation session. E.g. they must not hash memory addresses or other
88///    things that are "randomly" assigned per compilation session.
89///
90/// - `stable_hash()` must be independent of the host architecture. The
91///   `StableHasher` takes care of endianness and `isize`/`usize` platform
92///   differences.
93///
94/// # Consistency across compiler stages
95///
96/// Because the stage1 compiler is built against the bootstrap stdlib, but the stage2
97/// compiler uses in-tree stdlib, implementations of `StableHash` must not rely on `Hash`
98/// impls that were provided or derived by the standard library. Doing so leads to weird
99/// bugs and CI failures that can block changes to those stdlib hash impls.
100///
101/// (Unfortunately, as of late 2026 we have many stable-hash impls that _do_
102/// leak details of stdlib hash impls.)
103///
104/// See <https://github.com/rust-lang/rust/pull/164458> for more context.
105pub trait StableHash {
106    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher);
107}
108
109/// Implement this for types that can be turned into stable keys like, for
110/// example, for DefId that can be converted to a DefPathHash. This is used for
111/// bringing maps into a predictable order before hashing them.
112pub trait ToStableHashKey {
113    type KeyType: Ord + Sized + StableHash;
114    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> Self::KeyType;
115}
116
117/// Trait for marking a type as having a sort order that is
118/// stable across compilation session boundaries. More formally:
119///
120/// ```txt
121/// Ord::cmp(a1, b1) == Ord::cmp(a2, b2)
122///    where a2 = decode(encode(a1, context1), context2)
123///          b2 = decode(encode(b1, context1), context2)
124/// ```
125///
126/// i.e. the result of `Ord::cmp` is not influenced by encoding
127/// the values in one session and then decoding them in another
128/// session.
129///
130/// This is trivially true for types where encoding and decoding
131/// don't change the bytes of the values that are used during
132/// comparison and comparison only depends on these bytes (as
133/// opposed to some non-local state). Examples are u32, String,
134/// Path, etc.
135///
136/// But it is not true for:
137///  - `*const T` and `*mut T` because the values of these pointers
138///    will change between sessions.
139///  - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
140///    values depend on state that might be different between
141///    compilation sessions.
142///
143/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
144/// unstable sorting can be used for this type. Set to true if and
145/// only if `a == b` implies `a` and `b` are fully indistinguishable.
146pub trait StableOrd: Ord {
147    const CAN_USE_UNSTABLE_SORT: bool;
148
149    /// Marker to ensure that implementors have carefully considered
150    /// whether their `Ord` implementation obeys this trait's contract.
151    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: ();
152}
153
154impl<T: StableOrd> StableOrd for &T {
155    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
156
157    // Ordering of a reference is exactly that of the referent, and since
158    // the ordering of the referet is stable so must be the ordering of the
159    // reference.
160    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
161}
162
163/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
164/// compared in a cross-session stable way, but their `Ord` implementation is
165/// not stable. In such cases, a `StableOrd` implementation can be provided
166/// to offer a lightweight way for stable sorting. (The more heavyweight option
167/// is to sort via `ToStableHashKey`, but then sorting needs to have access to
168/// a stable hashing context and `ToStableHashKey` can also be expensive as in
169/// the case of `Symbol` where it has to allocate a `String`.)
170///
171/// See the documentation of [StableOrd] for how stable sort order is defined.
172/// The same definition applies here. Be careful when implementing this trait.
173pub trait StableCompare {
174    const CAN_USE_UNSTABLE_SORT: bool;
175
176    fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering;
177}
178
179/// `StableOrd` denotes that the type's `Ord` implementation is stable, so
180/// we can implement `StableCompare` by just delegating to `Ord`.
181impl<T: StableOrd> StableCompare for T {
182    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
183
184    fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering {
185        self.cmp(other)
186    }
187}
188
189/// Implement StableHash by just calling `Hash::hash()`. Also implement `StableOrd` for the type
190/// since that has the same requirements.
191///
192/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
193/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
194/// for examples). Therefore this macro is not exported and should only be used in the limited cases
195/// here in this module.
196///
197/// Use `#[derive(StableHash)]` instead.
198macro_rules! impl_stable_traits_for_trivial_type {
199    ($t:ty) => {
200        impl $crate::stable_hash::StableHash for $t {
201            #[inline]
202            fn stable_hash<Hcx>(
203                &self,
204                _: &mut Hcx,
205                hasher: &mut $crate::stable_hash::StableHasher,
206            ) {
207                ::std::hash::Hash::hash(self, hasher);
208            }
209        }
210
211        impl $crate::stable_hash::StableOrd for $t {
212            const CAN_USE_UNSTABLE_SORT: bool = true;
213
214            // Encoding and decoding doesn't change the bytes of trivial types
215            // and `Ord::cmp` depends only on those bytes.
216            const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
217        }
218    };
219}
220
221pub(crate) use impl_stable_traits_for_trivial_type;
222
223impl 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);
224impl 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);
225impl 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);
226impl 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);
227impl 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);
228
229impl 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);
230impl 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);
231impl 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);
232impl 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);
233impl 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);
234
235impl 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);
236impl 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);
237
238impl 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);
239impl 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!(());
240
241impl 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);
242
243// We need a custom impl as the default hash function will only hash half the bits. For stable
244// hashing we want to hash the full 128-bit hash.
245impl StableHash for Hash128 {
246    #[inline]
247    fn stable_hash<Hcx>(&self, _: &mut Hcx, hasher: &mut StableHasher) {
248        self.as_u128().hash(hasher);
249    }
250}
251
252impl StableOrd for Hash128 {
253    const CAN_USE_UNSTABLE_SORT: bool = true;
254
255    // Encoding and decoding doesn't change the bytes of `Hash128`
256    // and `Ord::cmp` depends only on those bytes.
257    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
258}
259
260impl StableHash for ! {
261    fn stable_hash<Hcx>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {
262        ::core::panicking::unreachable_default_msg()unreachable!()
263    }
264}
265
266impl<T> StableHash for PhantomData<T> {
267    fn stable_hash<Hcx>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {}
268}
269
270impl<T: StableHash + std::num::ZeroablePrimitive> StableHash for NonZero<T> {
271    #[inline]
272    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
273        self.get().stable_hash(hcx, hasher)
274    }
275}
276
277impl StableHash for f32 {
278    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
279        let val: u32 = self.to_bits();
280        val.stable_hash(hcx, hasher);
281    }
282}
283
284impl StableHash for f64 {
285    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
286        let val: u64 = self.to_bits();
287        val.stable_hash(hcx, hasher);
288    }
289}
290
291impl StableHash for ::std::cmp::Ordering {
292    #[inline]
293    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
294        (*self as i8).stable_hash(hcx, hasher);
295    }
296}
297
298impl<T1: StableHash> StableHash for (T1,) {
299    #[inline]
300    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
301        let (ref _0,) = *self;
302        _0.stable_hash(hcx, hasher);
303    }
304}
305
306impl<T1: StableHash, T2: StableHash> StableHash for (T1, T2) {
307    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
308        let (ref _0, ref _1) = *self;
309        _0.stable_hash(hcx, hasher);
310        _1.stable_hash(hcx, hasher);
311    }
312}
313
314impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
315    const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::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> StableHash for (T1, T2, T3)
323where
324    T1: StableHash,
325    T2: StableHash,
326    T3: StableHash,
327{
328    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
329        let (ref _0, ref _1, ref _2) = *self;
330        _0.stable_hash(hcx, hasher);
331        _1.stable_hash(hcx, hasher);
332        _2.stable_hash(hcx, hasher);
333    }
334}
335
336impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
337    const CAN_USE_UNSTABLE_SORT: bool =
338        T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
339
340    // Ordering of tuples is a pure function of their elements' ordering, and since
341    // the ordering of each element is stable so must be the ordering of the tuple.
342    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
343}
344
345impl<T1, T2, T3, T4> StableHash for (T1, T2, T3, T4)
346where
347    T1: StableHash,
348    T2: StableHash,
349    T3: StableHash,
350    T4: StableHash,
351{
352    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
353        let (ref _0, ref _1, ref _2, ref _3) = *self;
354        _0.stable_hash(hcx, hasher);
355        _1.stable_hash(hcx, hasher);
356        _2.stable_hash(hcx, hasher);
357        _3.stable_hash(hcx, hasher);
358    }
359}
360
361impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
362    const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
363        && T2::CAN_USE_UNSTABLE_SORT
364        && T3::CAN_USE_UNSTABLE_SORT
365        && T4::CAN_USE_UNSTABLE_SORT;
366
367    // Ordering of tuples is a pure function of their elements' ordering, and since
368    // the ordering of each element is stable so must be the ordering of the tuple.
369    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
370}
371
372impl<T: StableHash> StableHash for [T] {
373    default fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
374        self.len().stable_hash(hcx, hasher);
375        for item in self {
376            item.stable_hash(hcx, hasher);
377        }
378    }
379}
380
381impl StableHash for [u8] {
382    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
383        self.len().stable_hash(hcx, hasher);
384        hasher.write(self);
385    }
386}
387
388impl<T: StableHash> StableHash for Vec<T> {
389    #[inline]
390    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
391        self[..].stable_hash(hcx, hasher);
392    }
393}
394
395impl<K, V, R> StableHash for indexmap::IndexMap<K, V, R>
396where
397    K: StableHash + Eq + Hash,
398    V: StableHash,
399    R: BuildHasher,
400{
401    #[inline]
402    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
403        self.len().stable_hash(hcx, hasher);
404        for kv in self {
405            kv.stable_hash(hcx, hasher);
406        }
407    }
408}
409
410impl<K, R> StableHash for indexmap::IndexSet<K, R>
411where
412    K: StableHash + Eq + Hash,
413    R: BuildHasher,
414{
415    #[inline]
416    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
417        self.len().stable_hash(hcx, hasher);
418        for key in self {
419            key.stable_hash(hcx, hasher);
420        }
421    }
422}
423
424impl<A, const N: usize> StableHash for SmallVec<[A; N]>
425where
426    A: StableHash,
427{
428    #[inline]
429    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
430        self[..].stable_hash(hcx, hasher);
431    }
432}
433
434impl<T: StableHash> StableHash for ThinVec<T> {
435    #[inline]
436    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
437        self[..].stable_hash(hcx, hasher);
438    }
439}
440
441impl<T: ?Sized + StableHash> StableHash for Box<T> {
442    #[inline]
443    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
444        (**self).stable_hash(hcx, hasher);
445    }
446}
447
448impl<T: ?Sized + StableHash> StableHash for ::std::rc::Rc<T> {
449    #[inline]
450    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
451        (**self).stable_hash(hcx, hasher);
452    }
453}
454
455impl<T: ?Sized + StableHash> StableHash for ::std::sync::Arc<T> {
456    #[inline]
457    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
458        (**self).stable_hash(hcx, hasher);
459    }
460}
461
462impl StableHash for str {
463    #[inline]
464    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
465        self.as_bytes().stable_hash(hcx, hasher);
466    }
467}
468
469impl StableOrd for &str {
470    const CAN_USE_UNSTABLE_SORT: bool = true;
471
472    // Encoding and decoding doesn't change the bytes of string slices
473    // and `Ord::cmp` depends only on those bytes.
474    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
475}
476
477impl StableHash for String {
478    #[inline]
479    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
480        self[..].stable_hash(hcx, hasher);
481    }
482}
483
484impl StableOrd for String {
485    const CAN_USE_UNSTABLE_SORT: bool = true;
486
487    // String comparison only depends on their contents and the
488    // contents are not changed by (de-)serialization.
489    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
490}
491
492impl StableHash for bool {
493    #[inline]
494    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
495        (if *self { 1u8 } else { 0u8 }).stable_hash(hcx, hasher);
496    }
497}
498
499impl StableOrd for bool {
500    const CAN_USE_UNSTABLE_SORT: bool = true;
501
502    // sort order of bools is not changed by (de-)serialization.
503    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
504}
505
506impl<T> StableHash for Option<T>
507where
508    T: StableHash,
509{
510    #[inline]
511    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
512        if let Some(ref value) = *self {
513            1u8.stable_hash(hcx, hasher);
514            value.stable_hash(hcx, hasher);
515        } else {
516            0u8.stable_hash(hcx, hasher);
517        }
518    }
519}
520
521impl<T: StableOrd> StableOrd for Option<T> {
522    const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
523
524    // the Option wrapper does not add instability to comparison.
525    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
526}
527
528impl<T1, T2> StableHash for Result<T1, T2>
529where
530    T1: StableHash,
531    T2: StableHash,
532{
533    #[inline]
534    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
535        #[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Tag {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    Tag::Ok => 0u8.stable_hash(__hcx, __hasher),
                    Tag::Err => 1u8.stable_hash(__hcx, __hasher),
                }
                match *self { Tag::Ok => {} Tag::Err => {} }
            }
        }
    };StableHash)]
536        enum Tag {
537            Ok,
538            Err,
539        }
540        match *self {
541            Ok(ref x) => {
542                Tag::Ok.stable_hash(hcx, hasher);
543                x.stable_hash(hcx, hasher);
544            }
545            Err(ref x) => {
546                Tag::Err.stable_hash(hcx, hasher);
547                x.stable_hash(hcx, hasher);
548            }
549        }
550    }
551}
552
553impl<'a, T> StableHash for &'a T
554where
555    T: StableHash + ?Sized,
556{
557    #[inline]
558    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
559        (**self).stable_hash(hcx, hasher);
560    }
561}
562
563/// There is no way to stable-hash a `Discriminant` without leaking unstable
564/// details of how the host compiler chooses and hashes discriminants.
565///
566/// That would be bad, because stable hashes must be consistent between
567/// the stage1 compiler (built with the bootstrap compiler/stdlib)
568/// and the stage2 compiler (built with the in-tree compiler/stdlib).
569///
570/// See <https://github.com/rust-lang/rust/issues/164734> for more context.
571///
572/// If you need to manually stable-hash a discriminant, instead derive `StableHash`
573/// on a dedicated "tag" enum, and then hash the appropriate tag for each variant.
574/// For an example, see the impl of `StableHash for Result`.
575impl<T> !StableHash for std::mem::Discriminant<T> {}
576
577impl<T> StableHash for ::std::range::RangeInclusive<T>
578where
579    T: StableHash,
580{
581    #[inline]
582    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
583        self.start.stable_hash(hcx, hasher);
584        self.last.stable_hash(hcx, hasher);
585    }
586}
587
588impl<I: Idx, T> StableHash for IndexSlice<I, T>
589where
590    T: StableHash,
591{
592    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
593        self.len().stable_hash(hcx, hasher);
594        for v in &self.raw {
595            v.stable_hash(hcx, hasher);
596        }
597    }
598}
599
600impl<I: Idx, T> StableHash for IndexVec<I, T>
601where
602    T: StableHash,
603{
604    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
605        self.len().stable_hash(hcx, hasher);
606        for v in &self.raw {
607            v.stable_hash(hcx, hasher);
608        }
609    }
610}
611
612impl<I: Idx> StableHash for DenseBitSet<I> {
613    fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, hasher: &mut StableHasher) {
614        ::std::hash::Hash::hash(self, hasher);
615    }
616}
617
618impl<R: Idx, C: Idx> StableHash for bit_set::BitMatrix<R, C> {
619    fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, hasher: &mut StableHasher) {
620        ::std::hash::Hash::hash(self, hasher);
621    }
622}
623
624impl 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);
625
626impl StableHash for std::path::Path {
627    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
628        use std::path::{Component, Prefix};
629
630        /// Tag value to be mixed in with each kind of component/prefix.
631        #[derive(const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for Tag {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    Tag::StartOfPath => 0u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixVerbatim => 1u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixVerbatimUNC => 2u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixVerbatimDisk => 3u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixDeviceNS => 4u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixUNC => 5u8.stable_hash(__hcx, __hasher),
                    Tag::PrefixDisk => 6u8.stable_hash(__hcx, __hasher),
                    Tag::RootDir => 7u8.stable_hash(__hcx, __hasher),
                    Tag::CurDir => 8u8.stable_hash(__hcx, __hasher),
                    Tag::ParentDir => 9u8.stable_hash(__hcx, __hasher),
                    Tag::Normal => 10u8.stable_hash(__hcx, __hasher),
                    Tag::EndOfPath => 11u8.stable_hash(__hcx, __hasher),
                }
                match *self {
                    Tag::StartOfPath => {}
                    Tag::PrefixVerbatim => {}
                    Tag::PrefixVerbatimUNC => {}
                    Tag::PrefixVerbatimDisk => {}
                    Tag::PrefixDeviceNS => {}
                    Tag::PrefixUNC => {}
                    Tag::PrefixDisk => {}
                    Tag::RootDir => {}
                    Tag::CurDir => {}
                    Tag::ParentDir => {}
                    Tag::Normal => {}
                    Tag::EndOfPath => {}
                }
            }
        }
    };StableHash)]
632        enum Tag {
633            StartOfPath,
634            PrefixVerbatim,
635            PrefixVerbatimUNC,
636            PrefixVerbatimDisk,
637            PrefixDeviceNS,
638            PrefixUNC,
639            PrefixDisk,
640            RootDir,
641            CurDir,
642            ParentDir,
643            Normal,
644            EndOfPath,
645        }
646
647        // Explicitly tag the start of each path, so that empty paths always hash something.
648        Tag::StartOfPath.stable_hash(hcx, hasher);
649
650        for (i, component) in self.components().enumerate() {
651            // Mix in the index of each component, to avoid potentially trivial collisions
652            // between inputs like `("foo/bar", "baz")` and `("foo", "bar/baz")`.
653            i.stable_hash(hcx, hasher);
654            match component {
655                Component::Prefix(prefix) => match prefix.kind() {
656                    Prefix::Verbatim(os_str) => {
657                        Tag::PrefixVerbatim.stable_hash(hcx, hasher);
658                        os_str.stable_hash(hcx, hasher);
659                    }
660                    Prefix::VerbatimUNC(host, share) => {
661                        Tag::PrefixVerbatimUNC.stable_hash(hcx, hasher);
662                        host.stable_hash(hcx, hasher);
663                        share.stable_hash(hcx, hasher);
664                    }
665                    Prefix::VerbatimDisk(letter) => {
666                        Tag::PrefixVerbatimDisk.stable_hash(hcx, hasher);
667                        letter.stable_hash(hcx, hasher);
668                    }
669                    Prefix::DeviceNS(os_str) => {
670                        Tag::PrefixDeviceNS.stable_hash(hcx, hasher);
671                        os_str.stable_hash(hcx, hasher);
672                    }
673                    Prefix::UNC(host, share) => {
674                        Tag::PrefixUNC.stable_hash(hcx, hasher);
675                        host.stable_hash(hcx, hasher);
676                        share.stable_hash(hcx, hasher);
677                    }
678                    Prefix::Disk(letter) => {
679                        Tag::PrefixDisk.stable_hash(hcx, hasher);
680                        letter.stable_hash(hcx, hasher);
681                    }
682                },
683                Component::RootDir => Tag::RootDir.stable_hash(hcx, hasher),
684                Component::CurDir => Tag::CurDir.stable_hash(hcx, hasher),
685                Component::ParentDir => Tag::ParentDir.stable_hash(hcx, hasher),
686                Component::Normal(os_str) => {
687                    Tag::Normal.stable_hash(hcx, hasher);
688                    os_str.stable_hash(hcx, hasher);
689                }
690            }
691        }
692
693        // Explicitly tag the end of each path, so that empty paths always hash something.
694        // (Tagging the start and the end and the component-index is potentially overkill.)
695        Tag::EndOfPath.stable_hash(hcx, hasher);
696    }
697}
698
699impl StableOrd for std::path::Path {
700    /// FIXME(Zalathar): Unstably sorting paths is pre-existing behavior, but potentially wrong.
701    const CAN_USE_UNSTABLE_SORT: bool = true;
702    /// Stdlib path sorting should (hopefully) not change.
703    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
704}
705
706impl StableHash for std::path::PathBuf {
707    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
708        self.as_path().stable_hash(hcx, hasher);
709    }
710}
711
712impl StableOrd for std::path::PathBuf {
713    const CAN_USE_UNSTABLE_SORT: bool = <std::path::Path as StableOrd>::CAN_USE_UNSTABLE_SORT;
714    /// Stdlib path sorting should (hopefully) not change.
715    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
716}
717
718// It is not safe to implement StableHash for HashSet, HashMap or any other collection type
719// with unstable but observable iteration order.
720// See https://github.com/rust-lang/compiler-team/issues/533 for further information.
721impl<V> !StableHash for std::collections::HashSet<V> {}
722impl<K, V> !StableHash for std::collections::HashMap<K, V> {}
723
724impl<K, V> StableHash for ::std::collections::BTreeMap<K, V>
725where
726    K: StableHash + StableOrd,
727    V: StableHash,
728{
729    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
730        self.len().stable_hash(hcx, hasher);
731        for entry in self.iter() {
732            entry.stable_hash(hcx, hasher);
733        }
734    }
735}
736
737impl<K> StableHash for ::std::collections::BTreeSet<K>
738where
739    K: StableHash + StableOrd,
740{
741    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
742        self.len().stable_hash(hcx, hasher);
743        for entry in self.iter() {
744            entry.stable_hash(hcx, hasher);
745        }
746    }
747}
748
749/// Controls what data we do or do not hash.
750/// Whenever a `StableHash` implementation caches its
751/// result, it needs to include `StableHashControls` as part
752/// of the key, to ensure that it does not produce an incorrect
753/// result (for example, using a `Fingerprint` produced while
754/// hashing `Span`s when a `Fingerprint` without `Span`s is
755/// being requested)
756#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for StableHashControls {
}
#[automatically_derived]impl ::core::clone::Clone for StableHashControls {
    #[inline]
    fn clone(&self) -> Self {
        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: &Self) -> 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)]
757pub struct StableHashControls {
758    pub hash_spans: bool,
759}