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,
}
// 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.
#[cfg(feature = "nightly")]
unsafe impl StableOrd for Size {
impl StableOrd for Size {
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
/// 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 {
///
/// **Be careful when implementing this trait, as an incorrect
/// implementation can cause miscompilation!**
pub trait StableOrd: Ord {
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;
}
@ -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;
}
};
@ -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;
}
@ -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;
}
@ -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 =
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
for (T1, T2, T3, T4)
{
impl<T1: StableOrd, T2: StableOrd, T3: StableOrd, T4: StableOrd> 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
@ -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;
}
@ -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.
unsafe impl StableOrd for String {
impl StableOrd for String {
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.
unsafe impl StableOrd for bool {
// sort order of bools is not changed by (de-)serialization.
impl StableOrd for bool {
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.
unsafe impl<T: StableOrd> StableOrd for Option<T> {
// the Option wrapper does not add instability to comparison.
impl<T: StableOrd> StableOrd for Option<T> {
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;
}
// 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.
unsafe impl StableOrd for ItemLocalId {
impl StableOrd for ItemLocalId {
const CAN_USE_UNSTABLE_SORT: bool = true;
}

View File

@ -301,7 +301,7 @@ fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
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;
}

View File

@ -491,8 +491,8 @@ pub enum OutputType {
DepInfo,
}
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
unsafe impl StableOrd for OutputType {
// Trivial C-Style enums have a stable sort order across compilation sessions.
impl StableOrd for OutputType {
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.
unsafe impl StableOrd for DefPathHash {
// `DefPathHash` sort order is not affected (de)serialization.
impl StableOrd for DefPathHash {
const CAN_USE_UNSTABLE_SORT: bool = true;
}