diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a6662d4e0e4db..31c66a56bea7b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -427,11 +427,13 @@ pub struct Size { raw: u64, } -// Safety: Ord is implement as just comparing numerical values and numerical values -// are not changed by (de-)serialization. #[cfg(feature = "nightly")] -unsafe impl StableOrd for Size { +impl StableOrd for Size { const CAN_USE_UNSTABLE_SORT: bool = true; + + // `Ord` is implemented as just comparing numerical values and numerical values + // are not changed by (de-)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } // This is debug-printed a lot in larger structs, don't waste too much space there diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index b5bdf2e179042..a57f5067dd8d2 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -238,12 +238,21 @@ pub trait ToStableHashKey { /// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether /// unstable sorting can be used for this type. Set to true if and /// only if `a == b` implies `a` and `b` are fully indistinguishable. -pub unsafe trait StableOrd: Ord { +pub trait StableOrd: Ord { const CAN_USE_UNSTABLE_SORT: bool; + + /// Marker to ensure that implementors have carefully considered + /// whether their `Ord` implementation obeys this trait's contract. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: (); } -unsafe impl StableOrd for &T { +impl StableOrd for &T { const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; + + // Ordering of a reference is exactly that of the referent, and since + // the ordering of the referet is stable so must be the ordering of the + // reference. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } /// 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 { } } - unsafe impl $crate::stable_hasher::StableOrd for $t { + impl $crate::stable_hasher::StableOrd for $t { const CAN_USE_UNSTABLE_SORT: bool = true; + + // Encoding and decoding doesn't change the bytes of trivial types + // and `Ord::cmp` depends only on those bytes. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } }; } @@ -327,8 +340,12 @@ impl HashStable for Hash128 { } } -unsafe impl StableOrd for Hash128 { +impl StableOrd for Hash128 { const CAN_USE_UNSTABLE_SORT: bool = true; + + // Encoding and decoding doesn't change the bytes of `Hash128` + // and `Ord::cmp` depends only on those bytes. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for ! { @@ -392,8 +409,12 @@ impl, T2: HashStable, CTX> HashStable for (T1, T2) } } -unsafe impl StableOrd for (T1, T2) { +impl StableOrd for (T1, T2) { const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT; + + // Ordering of tuples is a pure function of their elements' ordering, and since + // the ordering of each element is stable so must be the ordering of the tuple. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for (T1, T2, T3) @@ -410,9 +431,13 @@ where } } -unsafe impl StableOrd for (T1, T2, T3) { +impl StableOrd for (T1, T2, T3) { const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT; + + // Ordering of tuples is a pure function of their elements' ordering, and since + // the ordering of each element is stable so must be the ordering of the tuple. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for (T1, T2, T3, T4) @@ -431,13 +456,15 @@ where } } -unsafe impl StableOrd - for (T1, T2, T3, T4) -{ +impl StableOrd for (T1, T2, T3, T4) { const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT && T4::CAN_USE_UNSTABLE_SORT; + + // Ordering of tuples is a pure function of their elements' ordering, and since + // the ordering of each element is stable so must be the ordering of the tuple. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl, CTX> HashStable for [T] { @@ -530,8 +557,12 @@ impl HashStable for str { } } -unsafe impl StableOrd for &str { +impl StableOrd for &str { const CAN_USE_UNSTABLE_SORT: bool = true; + + // Encoding and decoding doesn't change the bytes of string slices + // and `Ord::cmp` depends only on those bytes. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for String { @@ -541,10 +572,12 @@ impl HashStable for String { } } -// Safety: String comparison only depends on their contents and the -// contents are not changed by (de-)serialization. -unsafe impl StableOrd for String { +impl StableOrd for String { const CAN_USE_UNSTABLE_SORT: bool = true; + + // String comparison only depends on their contents and the + // contents are not changed by (de-)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl ToStableHashKey for String { @@ -570,9 +603,11 @@ impl HashStable for bool { } } -// Safety: sort order of bools is not changed by (de-)serialization. -unsafe impl StableOrd for bool { +impl StableOrd for bool { const CAN_USE_UNSTABLE_SORT: bool = true; + + // sort order of bools is not changed by (de-)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for Option @@ -590,9 +625,11 @@ where } } -// Safety: the Option wrapper does not add instability to comparison. -unsafe impl StableOrd for Option { +impl StableOrd for Option { const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; + + // the Option wrapper does not add instability to comparison. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl HashStable for Result diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index ac48746950709..c0ca1a8017eb2 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -165,10 +165,12 @@ impl ItemLocalId { pub const INVALID: ItemLocalId = ItemLocalId::MAX; } -// Safety: Ord is implement as just comparing the ItemLocalId's numerical -// values and these are not changed by (de-)serialization. -unsafe impl StableOrd for ItemLocalId { +impl StableOrd for ItemLocalId { const CAN_USE_UNSTABLE_SORT: bool = true; + + // `Ord` is implemented as just comparing the ItemLocalId's numerical + // values and these are not changed by (de-)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 5f1a03502a70f..f2a68e3567158 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -301,9 +301,12 @@ impl ToStableHashKey for WorkProductId { self.hash } } -unsafe impl StableOrd for WorkProductId { +impl StableOrd for WorkProductId { // Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well const CAN_USE_UNSTABLE_SORT: bool = true; + + // `WorkProductId` sort order is not affected by (de)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } // Some types are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 839cc51efcea8..2d38ad3713328 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -498,9 +498,11 @@ pub enum OutputType { DepInfo, } -// Safety: Trivial C-Style enums have a stable sort order across compilation sessions. -unsafe impl StableOrd for OutputType { +impl StableOrd for OutputType { const CAN_USE_UNSTABLE_SORT: bool = true; + + // Trivial C-Style enums have a stable sort order across compilation sessions. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } impl ToStableHashKey for OutputType { diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 1ac3a817bba56..5456303b36fe4 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -120,9 +120,11 @@ impl Default for DefPathHash { } } -// Safety: `DefPathHash` sort order is not affected (de)serialization. -unsafe impl StableOrd for DefPathHash { +impl StableOrd for DefPathHash { const CAN_USE_UNSTABLE_SORT: bool = true; + + // `DefPathHash` sort order is not affected by (de)serialization. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } /// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all