@@ -238,12 +238,21 @@ pub trait ToStableHashKey<HCX> {
238238/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
239239/// unstable sorting can be used for this type. Set to true if and
240240/// only if `a == b` implies `a` and `b` are fully indistinguishable.
241- pub unsafe trait StableOrd : Ord {
241+ pub trait StableOrd : Ord {
242242 const CAN_USE_UNSTABLE_SORT : bool ;
243+
244+ /// Marker to ensure that implementors have carefully considered
245+ /// whether their `Ord` implementation obeys this trait's contract.
246+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) ;
243247}
244248
245- unsafe impl < T : StableOrd > StableOrd for & T {
249+ impl < T : StableOrd > StableOrd for & T {
246250 const CAN_USE_UNSTABLE_SORT : bool = T :: CAN_USE_UNSTABLE_SORT ;
251+
252+ // Ordering of a reference is exactly that of the referent, and since
253+ // the ordering of the referet is stable so must be the ordering of the
254+ // reference.
255+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
247256}
248257
249258/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
@@ -290,8 +299,12 @@ macro_rules! impl_stable_traits_for_trivial_type {
290299 }
291300 }
292301
293- unsafe impl $crate:: stable_hasher:: StableOrd for $t {
302+ impl $crate:: stable_hasher:: StableOrd for $t {
294303 const CAN_USE_UNSTABLE_SORT : bool = true ;
304+
305+ // Encoding and decoding doesn't change the bytes of trivial types
306+ // and `Ord::cmp` depends only on those bytes.
307+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
295308 }
296309 } ;
297310}
@@ -327,8 +340,12 @@ impl<CTX> HashStable<CTX> for Hash128 {
327340 }
328341}
329342
330- unsafe impl StableOrd for Hash128 {
343+ impl StableOrd for Hash128 {
331344 const CAN_USE_UNSTABLE_SORT : bool = true ;
345+
346+ // Encoding and decoding doesn't change the bytes of `Hash128`
347+ // and `Ord::cmp` depends only on those bytes.
348+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
332349}
333350
334351impl < CTX > HashStable < CTX > for ! {
@@ -392,8 +409,12 @@ impl<T1: HashStable<CTX>, T2: HashStable<CTX>, CTX> HashStable<CTX> for (T1, T2)
392409 }
393410}
394411
395- unsafe impl < T1 : StableOrd , T2 : StableOrd > StableOrd for ( T1 , T2 ) {
412+ impl < T1 : StableOrd , T2 : StableOrd > StableOrd for ( T1 , T2 ) {
396413 const CAN_USE_UNSTABLE_SORT : bool = T1 :: CAN_USE_UNSTABLE_SORT && T2 :: CAN_USE_UNSTABLE_SORT ;
414+
415+ // Ordering of tuples is a pure function of their elements' ordering, and since
416+ // the ordering of each element is stable so must be the ordering of the tuple.
417+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
397418}
398419
399420impl < T1 , T2 , T3 , CTX > HashStable < CTX > for ( T1 , T2 , T3 )
@@ -410,9 +431,13 @@ where
410431 }
411432}
412433
413- unsafe impl < T1 : StableOrd , T2 : StableOrd , T3 : StableOrd > StableOrd for ( T1 , T2 , T3 ) {
434+ impl < T1 : StableOrd , T2 : StableOrd , T3 : StableOrd > StableOrd for ( T1 , T2 , T3 ) {
414435 const CAN_USE_UNSTABLE_SORT : bool =
415436 T1 :: CAN_USE_UNSTABLE_SORT && T2 :: CAN_USE_UNSTABLE_SORT && T3 :: CAN_USE_UNSTABLE_SORT ;
437+
438+ // Ordering of tuples is a pure function of their elements' ordering, and since
439+ // the ordering of each element is stable so must be the ordering of the tuple.
440+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
416441}
417442
418443impl < T1 , T2 , T3 , T4 , CTX > HashStable < CTX > for ( T1 , T2 , T3 , T4 )
@@ -431,13 +456,15 @@ where
431456 }
432457}
433458
434- unsafe impl < T1 : StableOrd , T2 : StableOrd , T3 : StableOrd , T4 : StableOrd > StableOrd
435- for ( T1 , T2 , T3 , T4 )
436- {
459+ impl < T1 : StableOrd , T2 : StableOrd , T3 : StableOrd , T4 : StableOrd > StableOrd for ( T1 , T2 , T3 , T4 ) {
437460 const CAN_USE_UNSTABLE_SORT : bool = T1 :: CAN_USE_UNSTABLE_SORT
438461 && T2 :: CAN_USE_UNSTABLE_SORT
439462 && T3 :: CAN_USE_UNSTABLE_SORT
440463 && T4 :: CAN_USE_UNSTABLE_SORT ;
464+
465+ // Ordering of tuples is a pure function of their elements' ordering, and since
466+ // the ordering of each element is stable so must be the ordering of the tuple.
467+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
441468}
442469
443470impl < T : HashStable < CTX > , CTX > HashStable < CTX > for [ T ] {
@@ -530,8 +557,12 @@ impl<CTX> HashStable<CTX> for str {
530557 }
531558}
532559
533- unsafe impl StableOrd for & str {
560+ impl StableOrd for & str {
534561 const CAN_USE_UNSTABLE_SORT : bool = true ;
562+
563+ // Encoding and decoding doesn't change the bytes of string slices
564+ // and `Ord::cmp` depends only on those bytes.
565+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
535566}
536567
537568impl < CTX > HashStable < CTX > for String {
@@ -541,10 +572,12 @@ impl<CTX> HashStable<CTX> for String {
541572 }
542573}
543574
544- // Safety: String comparison only depends on their contents and the
545- // contents are not changed by (de-)serialization.
546- unsafe impl StableOrd for String {
575+ impl StableOrd for String {
547576 const CAN_USE_UNSTABLE_SORT : bool = true ;
577+
578+ // String comparison only depends on their contents and the
579+ // contents are not changed by (de-)serialization.
580+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
548581}
549582
550583impl < HCX > ToStableHashKey < HCX > for String {
@@ -570,9 +603,11 @@ impl<CTX> HashStable<CTX> for bool {
570603 }
571604}
572605
573- // Safety: sort order of bools is not changed by (de-)serialization.
574- unsafe impl StableOrd for bool {
606+ impl StableOrd for bool {
575607 const CAN_USE_UNSTABLE_SORT : bool = true ;
608+
609+ // sort order of bools is not changed by (de-)serialization.
610+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
576611}
577612
578613impl < T , CTX > HashStable < CTX > for Option < T >
@@ -590,9 +625,11 @@ where
590625 }
591626}
592627
593- // Safety: the Option wrapper does not add instability to comparison.
594- unsafe impl < T : StableOrd > StableOrd for Option < T > {
628+ impl < T : StableOrd > StableOrd for Option < T > {
595629 const CAN_USE_UNSTABLE_SORT : bool = T :: CAN_USE_UNSTABLE_SORT ;
630+
631+ // the Option wrapper does not add instability to comparison.
632+ const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED : ( ) = ( ) ;
596633}
597634
598635impl < T1 , T2 , CTX > HashStable < CTX > for Result < T1 , T2 >
0 commit comments