Skip to content

Commit 6b272b0

Browse files
committed
Add Discriminant::unstable_cmp
Provides an unstable ordering between `Discriminant<T>` values.
1 parent d64de46 commit 6b272b0

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

‎library/core/src/marker.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ pub trait DiscriminantKind {
884884
/// The type of the discriminant, which must satisfy the trait
885885
/// bounds required by `mem::Discriminant`.
886886
#[lang = "discriminant_type"]
887-
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
887+
type Discriminant: Copy + Debug + Eq + Hash + Ord + Send + Sync + Unpin;
888888
}
889889

890890
/// Used to determine whether a type contains

‎library/core/src/mem/mod.rs‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,67 @@ impl<T> fmt::Debug for Discriminant<T> {
13251325
}
13261326
}
13271327

1328+
impl<T> Discriminant<T> {
1329+
/// Returns an *unstable* ordering between `self` and `other`.
1330+
///
1331+
/// [`Discriminant`] does not implement [`PartialOrd`] or [`Ord`] as we do
1332+
/// not guarantee a stable ordering of discriminant values.
1333+
/// This will _typically_ sort enum variants by their declaration order, but
1334+
/// this is *not* guaranteed.
1335+
/// Likewise, non-enum values (e.g., `struct`s) will _typically_ be trivially
1336+
/// ordered as equivalent.
1337+
///
1338+
/// Users of this function should instead rely on the [`Ord`] implementation
1339+
/// of `T` wherever possible.
1340+
///
1341+
/// # Examples
1342+
///
1343+
/// ```
1344+
/// #![feature(discriminant_cmp)]
1345+
///
1346+
/// use std::cmp::Ordering;
1347+
/// use std::mem::discriminant;
1348+
///
1349+
/// enum Foo { A(i32), B(i32) }
1350+
///
1351+
/// // Equivalent arms will compare equal regardless of contained data
1352+
/// assert!(matches!(
1353+
/// discriminant(&Foo::A(1)).unstable_cmp(&discriminant(&Foo::A(2))),
1354+
/// Ordering::Equal,
1355+
/// ));
1356+
///
1357+
/// // Inequivalent arms will compare not-equal
1358+
/// assert!(matches!(
1359+
/// discriminant(&Foo::A(1)).unstable_cmp(&discriminant(&Foo::B(1))),
1360+
/// Ordering::Less | Ordering::Greater,
1361+
/// ));
1362+
/// ```
1363+
///
1364+
/// Upstream libraries and the compiler are free to change the exact ordering
1365+
/// of discriminants. The below _may_ break at any time:
1366+
///
1367+
/// ```should_panic
1368+
/// # #![feature(discriminant_cmp)]
1369+
/// #
1370+
/// # use std::cmp::Ordering;
1371+
/// # use std::mem::discriminant;
1372+
/// #
1373+
/// # enum Foo { B(i32), A(i32) } // Deliberately swapped so this example panics
1374+
/// #
1375+
/// // Foo::A is declared before Foo::B, but that ordering is not stable
1376+
/// assert!(matches!(
1377+
/// discriminant(&Foo::A(0)).unstable_cmp(&discriminant(&Foo::B(0))),
1378+
/// Ordering::Less,
1379+
/// ));
1380+
/// ```
1381+
#[unstable(feature = "discriminant_cmp", issue = "none", reason = "not yet created")]
1382+
#[must_use]
1383+
#[inline]
1384+
pub fn unstable_cmp(&self, other: &Self) -> Ordering {
1385+
<<T as DiscriminantKind>::Discriminant as Ord>::cmp(&self.0, &other.0)
1386+
}
1387+
}
1388+
13281389
/// Returns a value uniquely identifying the enum variant in `v`.
13291390
///
13301391
/// If `T` is not an enum, calling this function will not result in undefined behavior, but the

0 commit comments

Comments
 (0)