@@ -219,42 +219,72 @@ pub trait ToStableHashKey<HCX> {
219
219
fn to_stable_hash_key ( & self , hcx : & HCX ) -> Self :: KeyType ;
220
220
}
221
221
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.
223
251
///
224
252
/// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting.
225
253
/// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013)
226
254
/// for examples). Therefore this macro is not exported and should only be used in the limited cases
227
255
/// here in this module.
228
256
///
229
257
/// Use `#[derive(HashStable_Generic)]` instead.
230
- macro_rules! impl_stable_hash_via_hash {
258
+ macro_rules! impl_stable_traits_for_trivial_type {
231
259
( $t: ty) => {
232
260
impl <CTX > $crate:: stable_hasher:: HashStable <CTX > for $t {
233
261
#[ inline]
234
262
fn hash_stable( & self , _: & mut CTX , hasher: & mut $crate:: stable_hasher:: StableHasher ) {
235
263
:: std:: hash:: Hash :: hash( self , hasher) ;
236
264
}
237
265
}
266
+
267
+ unsafe impl $crate:: stable_hasher:: StableOrd for $t { }
238
268
} ;
239
269
}
240
270
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_traits_for_trivial_type ! ( i8 ) ;
272
+ impl_stable_traits_for_trivial_type ! ( i16 ) ;
273
+ impl_stable_traits_for_trivial_type ! ( i32 ) ;
274
+ impl_stable_traits_for_trivial_type ! ( i64 ) ;
275
+ impl_stable_traits_for_trivial_type ! ( isize ) ;
246
276
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_traits_for_trivial_type ! ( u8 ) ;
278
+ impl_stable_traits_for_trivial_type ! ( u16 ) ;
279
+ impl_stable_traits_for_trivial_type ! ( u32 ) ;
280
+ impl_stable_traits_for_trivial_type ! ( u64 ) ;
281
+ impl_stable_traits_for_trivial_type ! ( usize ) ;
252
282
253
- impl_stable_hash_via_hash ! ( u128 ) ;
254
- impl_stable_hash_via_hash ! ( i128 ) ;
283
+ impl_stable_traits_for_trivial_type ! ( u128 ) ;
284
+ impl_stable_traits_for_trivial_type ! ( i128 ) ;
255
285
256
- impl_stable_hash_via_hash ! ( char ) ;
257
- impl_stable_hash_via_hash ! ( ( ) ) ;
286
+ impl_stable_traits_for_trivial_type ! ( char ) ;
287
+ impl_stable_traits_for_trivial_type ! ( ( ) ) ;
258
288
259
289
impl < CTX > HashStable < CTX > for ! {
260
290
fn hash_stable ( & self , _ctx : & mut CTX , _hasher : & mut StableHasher ) {
@@ -444,6 +474,10 @@ impl<CTX> HashStable<CTX> for String {
444
474
}
445
475
}
446
476
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
+
447
481
impl < HCX > ToStableHashKey < HCX > for String {
448
482
type KeyType = String ;
449
483
#[ inline]
@@ -459,6 +493,9 @@ impl<CTX> HashStable<CTX> for bool {
459
493
}
460
494
}
461
495
496
+ // Safety: sort order of bools is not changed by (de-)serialization.
497
+ unsafe impl StableOrd for bool { }
498
+
462
499
impl < T , CTX > HashStable < CTX > for Option < T >
463
500
where
464
501
T : HashStable < CTX > ,
@@ -474,6 +511,9 @@ where
474
511
}
475
512
}
476
513
514
+ // Safety: the Option wrapper does not add instability to comparison.
515
+ unsafe impl < T : StableOrd > StableOrd for Option < T > { }
516
+
477
517
impl < T1 , T2 , CTX > HashStable < CTX > for Result < T1 , T2 >
478
518
where
479
519
T1 : HashStable < CTX > ,
@@ -550,8 +590,8 @@ where
550
590
}
551
591
}
552
592
553
- impl_stable_hash_via_hash ! ( :: std:: path:: Path ) ;
554
- impl_stable_hash_via_hash ! ( :: std:: path:: PathBuf ) ;
593
+ impl_stable_traits_for_trivial_type ! ( :: std:: path:: Path ) ;
594
+ impl_stable_traits_for_trivial_type ! ( :: std:: path:: PathBuf ) ;
555
595
556
596
impl < K , V , R , HCX > HashStable < HCX > for :: std:: collections:: HashMap < K , V , R >
557
597
where
@@ -584,27 +624,26 @@ where
584
624
585
625
impl < K , V , HCX > HashStable < HCX > for :: std:: collections:: BTreeMap < K , V >
586
626
where
587
- K : ToStableHashKey < HCX > ,
627
+ K : HashStable < HCX > + StableOrd ,
588
628
V : HashStable < HCX > ,
589
629
{
590
630
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
+ }
596
635
}
597
636
}
598
637
599
638
impl < K , HCX > HashStable < HCX > for :: std:: collections:: BTreeSet < K >
600
639
where
601
- K : ToStableHashKey < HCX > ,
640
+ K : HashStable < HCX > + StableOrd ,
602
641
{
603
642
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
+ }
608
647
}
609
648
}
610
649
0 commit comments