Skip to content

Commit c290e9d

Browse files
committed
Auto merge of rust-lang#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](rust-lang/compiler-team#533), rust-lang#105175, `@michaelwoerister` r? `@Nilstrieb`
2 parents d929a42 + 0e73e70 commit c290e9d

File tree

6 files changed

+76
-28
lines changed

6 files changed

+76
-28
lines changed

compiler/rustc_abi/src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,13 @@ pub struct Size {
427427
raw: u64,
428428
}
429429

430-
// Safety: Ord is implement as just comparing numerical values and numerical values
431-
// are not changed by (de-)serialization.
432430
#[cfg(feature = "nightly")]
433-
unsafe impl StableOrd for Size {
431+
impl StableOrd for Size {
434432
const CAN_USE_UNSTABLE_SORT: bool = true;
433+
434+
// `Ord` is implemented as just comparing numerical values and numerical values
435+
// are not changed by (de-)serialization.
436+
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
435437
}
436438

437439
// This is debug-printed a lot in larger structs, don't waste too much space there

compiler/rustc_data_structures/src/stable_hasher.rs

+54-17
Original file line numberDiff line numberDiff line change
@@ -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

334351
impl<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

399420
impl<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

418443
impl<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

443470
impl<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

537568
impl<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

550583
impl<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

578613
impl<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

598635
impl<T1, T2, CTX> HashStable<CTX> for Result<T1, T2>

compiler/rustc_hir/src/hir_id.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,12 @@ impl ItemLocalId {
165165
pub const INVALID: ItemLocalId = ItemLocalId::MAX;
166166
}
167167

168-
// Safety: Ord is implement as just comparing the ItemLocalId's numerical
169-
// values and these are not changed by (de-)serialization.
170-
unsafe impl StableOrd for ItemLocalId {
168+
impl StableOrd for ItemLocalId {
171169
const CAN_USE_UNSTABLE_SORT: bool = true;
170+
171+
// `Ord` is implemented as just comparing the ItemLocalId's numerical
172+
// values and these are not changed by (de-)serialization.
173+
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
172174
}
173175

174176
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.

compiler/rustc_query_system/src/dep_graph/dep_node.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,12 @@ impl<HCX> ToStableHashKey<HCX> for WorkProductId {
301301
self.hash
302302
}
303303
}
304-
unsafe impl StableOrd for WorkProductId {
304+
impl StableOrd for WorkProductId {
305305
// Fingerprint can use unstable (just a tuple of `u64`s), so WorkProductId can as well
306306
const CAN_USE_UNSTABLE_SORT: bool = true;
307+
308+
// `WorkProductId` sort order is not affected by (de)serialization.
309+
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
307310
}
308311

309312
// Some types are used a lot. Make sure they don't unintentionally get bigger.

compiler/rustc_session/src/config.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -498,9 +498,11 @@ pub enum OutputType {
498498
DepInfo,
499499
}
500500

501-
// Safety: Trivial C-Style enums have a stable sort order across compilation sessions.
502-
unsafe impl StableOrd for OutputType {
501+
impl StableOrd for OutputType {
503502
const CAN_USE_UNSTABLE_SORT: bool = true;
503+
504+
// Trivial C-Style enums have a stable sort order across compilation sessions.
505+
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
504506
}
505507

506508
impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType {

compiler/rustc_span/src/def_id.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,11 @@ impl Default for DefPathHash {
120120
}
121121
}
122122

123-
// Safety: `DefPathHash` sort order is not affected (de)serialization.
124-
unsafe impl StableOrd for DefPathHash {
123+
impl StableOrd for DefPathHash {
125124
const CAN_USE_UNSTABLE_SORT: bool = true;
125+
126+
// `DefPathHash` sort order is not affected by (de)serialization.
127+
const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
126128
}
127129

128130
/// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all

0 commit comments

Comments
 (0)