From 3280db49e9dbce48f5ccdd03d13b3a95446e5a81 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Mon, 30 Dec 2024 08:48:15 +1100 Subject: [PATCH] Remove Eq trait bound The `PartialOrd` trait is object safe but `Ord` is not. We can make `ArbitraryOrd` object safe by softening the bounds and only requiring `PartialEq` - we still provide a blanket implementation of `Ord` if `Eq` is implemented for `T`. Add a unit test that verifies using `Box` - props to Poelstra for the idea. --- src/lib.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 09d680c..63ed658 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,7 +82,7 @@ use core::ops::{Deref, DerefMut}; /// } /// } /// ``` -pub trait ArbitraryOrd: Eq + PartialEq { +pub trait ArbitraryOrd: PartialEq { /// Implements a meaningless, arbitrary ordering. fn arbitrary_cmp(&self, other: &Rhs) -> Ordering; } @@ -154,11 +154,11 @@ impl ArbitraryOrd for &T { } impl PartialOrd for Ordered { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + fn partial_cmp(&self, other: &Self) -> Option { Some((*self).arbitrary_cmp(other)) } } -impl Ord for Ordered { - fn cmp(&self, other: &Self) -> Ordering { self.0.arbitrary_cmp(&other.0) } +impl Ord for Ordered { + fn cmp(&self, other: &Self) -> Ordering { (*self).arbitrary_cmp(other) } } impl fmt::Display for Ordered { @@ -260,4 +260,17 @@ mod tests { assert_send::>(); assert_sync::>(); } + + #[test] + fn trait_is_object_safe() { + extern crate std; + use std::boxed::Box; + + // If this test builds then `ArbitraryOrd` is object safe. + #[allow(dead_code)] + struct ObjectSafe { + p: Box>, + q: Box>, // Sanity check. + } + } }