rust-lang/rust · #165443
Add `Discriminant::ord`
library/core/src/marker.rs1 + / 1 −
@@ -884,7 +884,7 @@ pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. #[lang = "discriminant_type"]- type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;+ type Discriminant: Copy + Debug + Eq + Hash + Ord + Send + Sync + Unpin; } /// Used to determine whether a type containslibrary/core/src/mem/mod.rs128 + / 0 −
@@ -1285,6 +1285,82 @@ pub const unsafe fn transmute_neo<Src, Dst>(src: Src) -> Dst { #[stable(feature = "discriminant_value", since = "1.21.0")] pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant); +/// Implementation detail for [`Discriminant::ord`].+#[unstable(feature = "discriminant_ord", issue = "165438")]+pub struct DiscriminantOrd<T>(<T as DiscriminantKind>::Discriminant);++impl<T> Discriminant<T> {+ /// Returns an ordering key for this [`Discriminant`] that has an unstable+ /// implementation with regards to *semantic versioning*. This is not the be confused+ /// with an [*"unstable sort"*].+ ///+ /// Because all types have a publicly accessible [`Discriminant`], regardless+ /// of whether the order of said type is a part of its stability guarantees,+ /// the exact ordering of the returned [`DiscriminantOrd`] cannot be relied on+ /// for stability across crates. This is similar to the stability of the size+ /// of a type as returned by [`size_of`].+ ///+ /// Enum values will be ordered based on the source declaration and `repr` values+ /// of their variants, consistent with derived implementations of [`PartialOrd`]+ /// and [`Ord`]. Noting that only the discriminant and no field values are considered.+ /// All other kinds of values have an *unspecified* ordering, but will _typically_+ /// be trivially ordered as equivalent.+ ///+ /// Users of this function should instead rely on the [`Ord`] implementation+ /// of `T` wherever possible.+ ///+ /// # Examples+ ///+ /// ```+ /// #![feature(discriminant_ord)]+ ///+ /// use std::cmp::Ordering;+ /// use std::mem::discriminant;+ /// # use std::assert_matches;+ ///+ /// enum Foo { A(i32), B(i32) }+ ///+ /// // Equivalent arms will compare equal regardless of contained data+ /// assert_matches!(+ /// discriminant(&Foo::A(1)).ord().cmp(&discriminant(&Foo::A(2)).ord()),+ /// Ordering::Equal,+ /// );+ ///+ /// // Inequivalent arms will compare not-equal+ /// assert_matches!(+ /// discriminant(&Foo::A(1)).ord().cmp(&discriminant(&Foo::B(1)).ord()),+ /// Ordering::Less | Ordering::Greater,+ /// );+ /// ```+ ///+ /// Upstream libraries and the compiler are free to change the exact ordering+ /// of discriminants. The below _may_ break at any time:+ ///+ /// ```should_panic+ /// # #![feature(discriminant_ord)]+ /// #+ /// # use std::cmp::Ordering;+ /// # use std::mem::discriminant;+ /// # use std::assert_matches;+ /// #+ /// # enum Foo { B(i32), A(i32) } // Deliberately swapped so this example panics+ /// #+ /// // Foo::A is declared before Foo::B, but that ordering is not stable+ /// assert_matches!(+ /// discriminant(&Foo::A(0)).ord().cmp(&discriminant(&Foo::B(0)).ord()),+ /// Ordering::Less,+ /// );+ /// ```+ ///+ /// ["unstable sort"]: slice::sort_unstable+ #[unstable(feature = "discriminant_ord", issue = "165438")]+ #[must_use]+ #[inline]+ pub const fn ord(&self) -> DiscriminantOrd<T> {+ DiscriminantOrd::<T>(self.0)+ }+}+ // N.B. These trait implementations cannot be derived because we don't want any bounds on T. #[stable(feature = "discriminant_value", since = "1.21.0")]@@ -1325,6 +1401,58 @@ impl<T> fmt::Debug for Discriminant<T> { } } +#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> Copy for DiscriminantOrd<T> {}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> clone::Clone for DiscriminantOrd<T> {+ fn clone(&self) -> Self {+ *self+ }+}++#[doc(hidden)]+#[unstable(feature = "trivial_clone", issue = "none")]+unsafe impl<T> TrivialClone for DiscriminantOrd<T> {}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> cmp::PartialEq for DiscriminantOrd<T> {+ fn eq(&self, rhs: &Self) -> bool {+ self.0 == rhs.0+ }+}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> cmp::Eq for DiscriminantOrd<T> {}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> hash::Hash for DiscriminantOrd<T> {+ fn hash<H: hash::Hasher>(&self, state: &mut H) {+ self.0.hash(state);+ }+}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> fmt::Debug for DiscriminantOrd<T> {+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {+ fmt.debug_tuple("DiscriminantOrd").field(&self.0).finish()+ }+}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> cmp::PartialOrd for DiscriminantOrd<T> {+ fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {+ self.0.partial_cmp(&other.0)+ }+}++#[unstable(feature = "discriminant_ord", issue = "165438")]+impl<T> cmp::Ord for DiscriminantOrd<T> {+ fn cmp(&self, other: &Self) -> cmp::Ordering {+ self.0.cmp(&other.0)+ }+}+ /// Returns a value uniquely identifying the enum variant in `v`. /// /// If `T` is not an enum, calling this function will not result in undefined behavior, but the