@@ -219,42 +219,72 @@ pub trait ToStableHashKey<HCX> {
219219 fn to_stable_hash_key ( & self , hcx : & HCX ) -> Self :: KeyType ;
220220}
221221
222- /// Implement HashStable by just calling `Hash::hash()`.
222+ /// Trait for marking a type as having a sort order that is
223+ /// stable across compilation session boundaries. More formally:
224+ ///
225+ /// ```txt
226+ /// Ord::cmp(a1, b1) == Ord:cmp(a2, b2)
227+ /// where a2 = decode(encode(a1, context1), context2)
228+ /// b2 = decode(encode(b1, context1), context2)
229+ /// ```
230+ ///
231+ /// i.e. the result of `Ord::cmp` is not influenced by encoding
232+ /// the values in one session and then decoding them in another
233+ /// session.
234+ ///
235+ /// This is trivially true for types where encoding and decoding
236+ /// don't change the bytes of the values that are used during
237+ /// comparison and comparison only depends on these bytes (as
238+ /// opposed to some non-local state). Examples are u32, String,
239+ /// Path, etc.
240+ ///
241+ /// But it is not true for:
242+ /// - `*const T` and `*mut T` because the values of these pointers
243+ /// will change between sessions.
244+ /// - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete
245+ /// values depend on state that might be different between
246+ /// compilation sessions.
247+ pub unsafe trait StableOrd : Ord { }
248+
249+ /// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since
250+ /// that has the same requirements.
223251///
224252/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
225253/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
226254/// for examples). Therefore this macro is not exported and should only be used in the limited cases
227255/// here in this module.
228256///
229257/// Use `#[derive(HashStable_Generic)]` instead.
230- macro_rules! impl_stable_hash_via_hash {
258+ macro_rules! impl_stable_ord_and_stable_hash_via_hash {
231259 ( $t: ty) => {
232260 impl <CTX > $crate:: stable_hasher:: HashStable <CTX > for $t {
233261 #[ inline]
234262 fn hash_stable( & self , _: & mut CTX , hasher: & mut $crate:: stable_hasher:: StableHasher ) {
235263 :: std:: hash:: Hash :: hash( self , hasher) ;
236264 }
237265 }
266+
267+ unsafe impl $crate:: stable_hasher:: StableOrd for $t { }
238268 } ;
239269}
240270
241- impl_stable_hash_via_hash ! ( i8 ) ;
242- impl_stable_hash_via_hash ! ( i16 ) ;
243- impl_stable_hash_via_hash ! ( i32 ) ;
244- impl_stable_hash_via_hash ! ( i64 ) ;
245- impl_stable_hash_via_hash ! ( isize ) ;
271+ impl_stable_ord_and_stable_hash_via_hash ! ( i8 ) ;
272+ impl_stable_ord_and_stable_hash_via_hash ! ( i16 ) ;
273+ impl_stable_ord_and_stable_hash_via_hash ! ( i32 ) ;
274+ impl_stable_ord_and_stable_hash_via_hash ! ( i64 ) ;
275+ impl_stable_ord_and_stable_hash_via_hash ! ( isize ) ;
246276
247- impl_stable_hash_via_hash ! ( u8 ) ;
248- impl_stable_hash_via_hash ! ( u16 ) ;
249- impl_stable_hash_via_hash ! ( u32 ) ;
250- impl_stable_hash_via_hash ! ( u64 ) ;
251- impl_stable_hash_via_hash ! ( usize ) ;
277+ impl_stable_ord_and_stable_hash_via_hash ! ( u8 ) ;
278+ impl_stable_ord_and_stable_hash_via_hash ! ( u16 ) ;
279+ impl_stable_ord_and_stable_hash_via_hash ! ( u32 ) ;
280+ impl_stable_ord_and_stable_hash_via_hash ! ( u64 ) ;
281+ impl_stable_ord_and_stable_hash_via_hash ! ( usize ) ;
252282
253- impl_stable_hash_via_hash ! ( u128 ) ;
254- impl_stable_hash_via_hash ! ( i128 ) ;
283+ impl_stable_ord_and_stable_hash_via_hash ! ( u128 ) ;
284+ impl_stable_ord_and_stable_hash_via_hash ! ( i128 ) ;
255285
256- impl_stable_hash_via_hash ! ( char ) ;
257- impl_stable_hash_via_hash ! ( ( ) ) ;
286+ impl_stable_ord_and_stable_hash_via_hash ! ( char ) ;
287+ impl_stable_ord_and_stable_hash_via_hash ! ( ( ) ) ;
258288
259289impl < CTX > HashStable < CTX > for ! {
260290 fn hash_stable ( & self , _ctx : & mut CTX , _hasher : & mut StableHasher ) {
@@ -444,6 +474,10 @@ impl<CTX> HashStable<CTX> for String {
444474 }
445475}
446476
477+ // Safety: String comparison only depends on their contents and the
478+ // contents are not changed by (de-)serialization.
479+ unsafe impl StableOrd for String { }
480+
447481impl < HCX > ToStableHashKey < HCX > for String {
448482 type KeyType = String ;
449483 #[ inline]
@@ -459,6 +493,9 @@ impl<CTX> HashStable<CTX> for bool {
459493 }
460494}
461495
496+ // Safety: sort order of bools is not changed by (de-)serialization.
497+ unsafe impl StableOrd for bool { }
498+
462499impl < T , CTX > HashStable < CTX > for Option < T >
463500where
464501 T : HashStable < CTX > ,
@@ -474,6 +511,9 @@ where
474511 }
475512}
476513
514+ // Safety: the Option wrapper does not add instability to comparison.
515+ unsafe impl < T : StableOrd > StableOrd for Option < T > { }
516+
477517impl < T1 , T2 , CTX > HashStable < CTX > for Result < T1 , T2 >
478518where
479519 T1 : HashStable < CTX > ,
@@ -550,8 +590,8 @@ where
550590 }
551591}
552592
553- impl_stable_hash_via_hash ! ( :: std:: path:: Path ) ;
554- impl_stable_hash_via_hash ! ( :: std:: path:: PathBuf ) ;
593+ impl_stable_ord_and_stable_hash_via_hash ! ( :: std:: path:: Path ) ;
594+ impl_stable_ord_and_stable_hash_via_hash ! ( :: std:: path:: PathBuf ) ;
555595
556596impl < K , V , R , HCX > HashStable < HCX > for :: std:: collections:: HashMap < K , V , R >
557597where
@@ -584,27 +624,26 @@ where
584624
585625impl < K , V , HCX > HashStable < HCX > for :: std:: collections:: BTreeMap < K , V >
586626where
587- K : ToStableHashKey < HCX > ,
627+ K : HashStable < HCX > + StableOrd ,
588628 V : HashStable < HCX > ,
589629{
590630 fn hash_stable ( & self , hcx : & mut HCX , hasher : & mut StableHasher ) {
591- stable_hash_reduce ( hcx, hasher, self . iter ( ) , self . len ( ) , |hasher, hcx, ( key, value) | {
592- let key = key. to_stable_hash_key ( hcx) ;
593- key. hash_stable ( hcx, hasher) ;
594- value. hash_stable ( hcx, hasher) ;
595- } ) ;
631+ self . len ( ) . hash_stable ( hcx, hasher) ;
632+ for entry in self . iter ( ) {
633+ entry. hash_stable ( hcx, hasher) ;
634+ }
596635 }
597636}
598637
599- impl < K , HCX > HashStable < HCX > for :: std:: collections:: BTreeSet < K >
638+ impl < K : StableOrd , HCX > HashStable < HCX > for :: std:: collections:: BTreeSet < K >
600639where
601- K : ToStableHashKey < HCX > ,
640+ K : HashStable < HCX > + StableOrd ,
602641{
603642 fn hash_stable ( & self , hcx : & mut HCX , hasher : & mut StableHasher ) {
604- stable_hash_reduce ( hcx , hasher , self . iter ( ) , self . len ( ) , |hasher , hcx, key| {
605- let key = key . to_stable_hash_key ( hcx ) ;
606- key . hash_stable ( hcx, hasher) ;
607- } ) ;
643+ self . len ( ) . hash_stable ( hcx, hasher ) ;
644+ for entry in self . iter ( ) {
645+ entry . hash_stable ( hcx, hasher) ;
646+ }
608647 }
609648}
610649
0 commit comments