Auto merge of #126326 - eggyal:ununsafe-StableOrd, r=michaelwoerister
Un-unsafe the `StableOrd` trait Whilst incorrect implementations of this trait can cause miscompilation, they cannot cause memory unsafety in rustc. [Discussed on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Policy.20of.20.60unsafe.60.20within.20the.20compiler). cc [MCP 533](https://github.com/rust-lang/compiler-team/issues/533), #105175, `@michaelwoerister` r? `@Nilstrieb`
This commit is contained in:
commit
c290e9de32
@ -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
|
||||
|
@ -238,12 +238,21 @@ 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 {
|
||||
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<T: StableOrd> StableOrd for &T {
|
||||
impl<T: StableOrd> 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 @@ 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;
|
||||
|
||||
// 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 @@ 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;
|
||||
|
||||
// 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<CTX> HashStable<CTX> for ! {
|
||||
@ -392,8 +409,12 @@ 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;
|
||||
|
||||
// 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<T1, T2, T3, CTX> HashStable<CTX> for (T1, T2, T3)
|
||||
@ -410,9 +431,13 @@ 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;
|
||||
|
||||
// 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<T1, T2, T3, T4, CTX> HashStable<CTX> for (T1, T2, T3, T4)
|
||||
@ -431,13 +456,15 @@ 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
|
||||
&& 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<T: HashStable<CTX>, CTX> HashStable<CTX> for [T] {
|
||||
@ -530,8 +557,12 @@ 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;
|
||||
|
||||
// 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<CTX> HashStable<CTX> for String {
|
||||
@ -541,10 +572,12 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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<HCX> ToStableHashKey<HCX> for String {
|
||||
@ -570,9 +603,11 @@ 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 {
|
||||
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<T, CTX> HashStable<CTX> for Option<T>
|
||||
@ -590,9 +625,11 @@ 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> {
|
||||
impl<T: StableOrd> StableOrd for Option<T> {
|
||||
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<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>
|
||||
|
@ -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`.
|
||||
|
@ -301,9 +301,12 @@ 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;
|
||||
|
||||
// `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.
|
||||
|
@ -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<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {
|
||||
|
@ -120,9 +120,11 @@ fn default() -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user