Un-unsafe the StableOrd trait

Whilst incorrect implementations of this trait can cause miscompilation,
they cannot cause memory unsafety in rustc.
This commit is contained in:
Alan Egerton 2024-06-12 13:01:22 +01:00
parent 02c7a5921e
commit 114dd2061e
No known key found for this signature in database
GPG Key ID: 7D4C2F6C22122532
6 changed files with 26 additions and 25 deletions

View File

@ -425,10 +425,10 @@ pub struct Size {
raw: u64, raw: u64,
} }
// Safety: Ord is implement as just comparing numerical values and numerical values // Ord is implement as just comparing numerical values and numerical values
// are not changed by (de-)serialization. // are not changed by (de-)serialization.
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
unsafe impl StableOrd for Size { impl StableOrd for Size {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }

View File

@ -238,11 +238,14 @@ pub trait ToStableHashKey<HCX> {
/// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether /// The associated constant `CAN_USE_UNSTABLE_SORT` denotes whether
/// unstable sorting can be used for this type. Set to true if and /// unstable sorting can be used for this type. Set to true if and
/// only if `a == b` implies `a` and `b` are fully indistinguishable. /// only if `a == b` implies `a` and `b` are fully indistinguishable.
pub unsafe trait StableOrd: Ord { ///
/// **Be careful when implementing this trait, as an incorrect
/// implementation can cause miscompilation!**
pub trait StableOrd: Ord {
const CAN_USE_UNSTABLE_SORT: bool; const CAN_USE_UNSTABLE_SORT: bool;
} }
unsafe impl<T: StableOrd> StableOrd for &T { impl<T: StableOrd> StableOrd for &T {
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
} }
@ -290,7 +293,7 @@ fn hash_stable(&self, _: &mut CTX, hasher: &mut $crate::stable_hasher::StableHas
} }
} }
unsafe impl $crate::stable_hasher::StableOrd for $t { impl $crate::stable_hasher::StableOrd for $t {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }
}; };
@ -327,7 +330,7 @@ fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
} }
} }
unsafe impl StableOrd for Hash128 { impl StableOrd for Hash128 {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }
@ -392,7 +395,7 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
unsafe impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) { impl<T1: StableOrd, T2: StableOrd> StableOrd for (T1, T2) {
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT; const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT;
} }
@ -410,7 +413,7 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) { impl<T1: StableOrd, T2: StableOrd, T3: StableOrd> StableOrd for (T1, T2, T3) {
const CAN_USE_UNSTABLE_SORT: bool = const CAN_USE_UNSTABLE_SORT: bool =
T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT; T1::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT;
} }
@ -431,9 +434,7 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
unsafe impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> StableOrd for (T1, T2, T3, T4) {
for (T1, T2, T3, T4)
{
const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT
&& T2::CAN_USE_UNSTABLE_SORT && T2::CAN_USE_UNSTABLE_SORT
&& T3::CAN_USE_UNSTABLE_SORT && T3::CAN_USE_UNSTABLE_SORT
@ -530,7 +531,7 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
unsafe impl StableOrd for &str { impl StableOrd for &str {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }
@ -541,9 +542,9 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
// Safety: String comparison only depends on their contents and the // String comparison only depends on their contents and the
// contents are not changed by (de-)serialization. // contents are not changed by (de-)serialization.
unsafe impl StableOrd for String { impl StableOrd for String {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }
@ -570,8 +571,8 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
// Safety: sort order of bools is not changed by (de-)serialization. // 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; const CAN_USE_UNSTABLE_SORT: bool = true;
} }
@ -590,8 +591,8 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
} }
} }
// Safety: the Option wrapper does not add instability to comparison. // the Option wrapper does not add instability to comparison.
unsafe impl<T: StableOrd> StableOrd for Option<T> { impl<T: StableOrd> StableOrd for Option<T> {
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
} }

View File

@ -165,9 +165,9 @@ impl ItemLocalId {
pub const INVALID: ItemLocalId = ItemLocalId::MAX; pub const INVALID: ItemLocalId = ItemLocalId::MAX;
} }
// Safety: Ord is implement as just comparing the ItemLocalId's numerical // Ord is implement as just comparing the ItemLocalId's numerical
// values and these are not changed by (de-)serialization. // 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; const CAN_USE_UNSTABLE_SORT: bool = true;
} }

View File

@ -301,7 +301,7 @@ fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
self.hash 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 // Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }

View File

@ -491,8 +491,8 @@ pub enum OutputType {
DepInfo, DepInfo,
} }
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions. // 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; const CAN_USE_UNSTABLE_SORT: bool = true;
} }

View File

@ -120,8 +120,8 @@ fn default() -> Self {
} }
} }
// Safety: `DefPathHash` sort order is not affected (de)serialization. // `DefPathHash` sort order is not affected (de)serialization.
unsafe impl StableOrd for DefPathHash { impl StableOrd for DefPathHash {
const CAN_USE_UNSTABLE_SORT: bool = true; const CAN_USE_UNSTABLE_SORT: bool = true;
} }