rust/library/core/src/cmp.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1949 lines
60 KiB
Rust
Raw Normal View History

//! Utilities for comparing and ordering values.
//!
//! This module contains various tools for comparing and ordering values. In
2019-01-10 20:21:01 +00:00
//! summary:
2016-09-26 18:43:54 +00:00
//!
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
//! * [`PartialEq<Rhs>`] overloads the `==` and `!=` operators. In cases where
//! `Rhs` (the right hand side's type) is `Self`, this trait corresponds to a
//! partial equivalence relation.
//! * [`Eq`] indicates that the overloaded `==` operator corresponds to an
//! equivalence relation.
2019-01-10 20:21:01 +00:00
//! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and
//! partial orderings between values, respectively. Implementing them overloads
//! the `<`, `<=`, `>`, and `>=` operators.
//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
//! [`PartialOrd`], and describes an ordering of two values (less, equal, or
//! greater).
//! * [`Reverse`] is a struct that allows you to easily reverse an ordering.
//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you
//! to find the maximum or minimum of two values.
2016-03-14 15:43:55 +00:00
//!
2019-01-10 20:21:01 +00:00
//! For more details, see the respective documentation of each item in the list.
//!
2020-08-10 21:16:01 +00:00
//! [`max`]: Ord::max
//! [`min`]: Ord::min
2015-01-24 05:48:20 +00:00
#![stable(feature = "rust1", since = "1.0.0")]
mod bytewise;
pub(crate) use bytewise::BytewiseEq;
use self::Ordering::*;
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
/// Trait for comparisons using the equality operator.
///
/// Implementing this trait for types provides the `==` and `!=` operators for
/// those types.
///
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
/// We use the easier-to-read infix notation in the remainder of this documentation.
///
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
/// This trait allows for comparisons using the equality operator, for types
/// that do not have a full equivalence relation. For example, in floating point
/// numbers `NaN != NaN`, so floating point types implement `PartialEq` but not
/// [`trait@Eq`]. Formally speaking, when `Rhs == Self`, this trait corresponds
/// to a [partial equivalence relation].
///
/// [partial equivalence relation]: https://en.wikipedia.org/wiki/Partial_equivalence_relation
///
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
///
/// - `a != b` if and only if `!(a == b)`.
///
/// The default implementation of `ne` provides this consistency and is almost
/// always sufficient. It should not be overridden without very good reason.
///
/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
/// be consistent with `PartialEq` (see the documentation of those traits for the exact
2021-06-25 20:18:56 +00:00
/// requirements). It's easy to accidentally make them disagree by deriving some of the traits and
/// manually implementing others.
///
/// The equality relation `==` must satisfy the following conditions
/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
///
/// - **Symmetry**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
/// implies `b == a`**; and
///
/// - **Transitivity**: if `A: PartialEq<B>` and `B: PartialEq<C>` and `A:
/// PartialEq<C>`, then **`a == b` and `b == c` implies `a == c`**.
/// This must also work for longer chains, such as when `A: PartialEq<B>`, `B: PartialEq<C>`,
/// `C: PartialEq<D>`, and `A: PartialEq<D>` all exist.
///
/// Note that the `B: PartialEq<A>` (symmetric) and `A: PartialEq<C>`
/// (transitive) impls are not forced to exist, but these requirements apply
/// whenever they do exist.
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
/// ## Cross-crate considerations
///
/// Upholding the requirements stated above can become tricky when one crate implements `PartialEq`
/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the
/// standard library). The recommendation is to never implement this trait for a foreign type. In
/// other words, such a crate should do `impl PartialEq<ForeignType> for LocalType`, but it should
/// *not* do `impl PartialEq<LocalType> for ForeignType`.
///
/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local
/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T == U`. In
/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ...
/// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the
/// crate defining `T` already knows about. This rules out transitive chains where downstream crates
/// can add new `impl`s that "stitch together" comparisons of foreign types in ways that violate
/// transitivity.
///
/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding
/// more `PartialEq` implementations can cause build failures in downstream crates.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d on structs, two
/// instances are equal if all fields are equal, and not equal if any fields
/// are not equal. When `derive`d on enums, two instances are equal if they
/// are the same variant and all fields are equal.
2016-03-14 15:43:55 +00:00
///
/// ## How can I implement `PartialEq`?
///
/// An example implementation for a domain in which two books are considered
/// the same book if their ISBN matches, even if the formats differ:
///
/// ```
2018-08-21 21:24:23 +00:00
/// enum BookFormat {
/// Paperback,
/// Hardback,
/// Ebook,
/// }
///
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
/// }
///
/// impl PartialEq for Book {
/// fn eq(&self, other: &Self) -> bool {
/// self.isbn == other.isbn
/// }
/// }
///
/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
/// let b3 = Book { isbn: 10, format: BookFormat::Paperback };
///
/// assert!(b1 == b2);
/// assert!(b1 != b3);
/// ```
///
2018-08-21 21:24:23 +00:00
/// ## How can I compare two different types?
///
/// The type you can compare with is controlled by `PartialEq`'s type parameter.
/// For example, let's tweak our previous code a bit:
///
/// ```
/// // The derive implements <BookFormat> == <BookFormat> comparisons
2019-01-06 20:18:22 +00:00
/// #[derive(PartialEq)]
2018-08-21 21:24:23 +00:00
/// enum BookFormat {
/// Paperback,
/// Hardback,
/// Ebook,
/// }
///
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
/// }
///
/// // Implement <Book> == <BookFormat> comparisons
2018-08-21 21:24:23 +00:00
/// impl PartialEq<BookFormat> for Book {
/// fn eq(&self, other: &BookFormat) -> bool {
/// self.format == *other
2018-08-21 21:24:23 +00:00
/// }
/// }
///
/// // Implement <BookFormat> == <Book> comparisons
/// impl PartialEq<Book> for BookFormat {
2018-08-21 21:24:23 +00:00
/// fn eq(&self, other: &Book) -> bool {
2019-01-06 03:52:13 +00:00
/// *self == other.format
2018-08-21 21:24:23 +00:00
/// }
/// }
///
/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
///
/// assert!(b1 == BookFormat::Paperback);
/// assert!(BookFormat::Ebook != b1);
2018-08-21 21:24:23 +00:00
/// ```
///
/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
/// we allow `BookFormat`s to be compared with `Book`s.
2018-08-21 21:24:23 +00:00
///
/// A comparison like the one above, which ignores some fields of the struct,
/// can be dangerous. It can easily lead to an unintended violation of the
/// requirements for a partial equivalence relation. For example, if we kept
/// the above implementation of `PartialEq<Book>` for `BookFormat` and added an
/// implementation of `PartialEq<Book>` for `Book` (either via a `#[derive]` or
/// via the manual implementation from the first example) then the result would
/// violate transitivity:
///
/// ```should_panic
/// #[derive(PartialEq)]
2018-08-21 21:24:23 +00:00
/// enum BookFormat {
/// Paperback,
/// Hardback,
/// Ebook,
/// }
///
/// #[derive(PartialEq)]
2018-08-21 21:24:23 +00:00
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
/// }
///
/// impl PartialEq<BookFormat> for Book {
/// fn eq(&self, other: &BookFormat) -> bool {
/// self.format == *other
/// }
/// }
2019-01-12 16:19:02 +00:00
///
/// impl PartialEq<Book> for BookFormat {
/// fn eq(&self, other: &Book) -> bool {
/// *self == other.format
2018-08-21 21:24:23 +00:00
/// }
/// }
///
/// fn main() {
/// let b1 = Book { isbn: 1, format: BookFormat::Paperback };
/// let b2 = Book { isbn: 2, format: BookFormat::Paperback };
2018-08-21 21:24:23 +00:00
///
/// assert!(b1 == BookFormat::Paperback);
/// assert!(BookFormat::Paperback == b2);
2018-08-21 21:24:23 +00:00
///
/// // The following should hold by transitivity but doesn't.
/// assert!(b1 == b2); // <-- PANICS
/// }
2018-08-21 21:24:23 +00:00
/// ```
///
2016-03-14 15:43:55 +00:00
/// # Examples
///
/// ```
/// let x: u32 = 0;
/// let y: u32 = 1;
///
/// assert_eq!(x == y, false);
/// assert_eq!(x.eq(&y), false);
/// ```
2020-01-29 12:32:37 +00:00
///
/// [`eq`]: PartialEq::eq
/// [`ne`]: PartialEq::ne
#[lang = "eq"]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2018-04-25 18:10:58 +00:00
#[doc(alias = "==")]
#[doc(alias = "!=")]
2022-08-28 06:27:15 +00:00
#[rustc_on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} == {Rhs}`",
append_const_msg
)]
#[rustc_diagnostic_item = "PartialEq"]
pub trait PartialEq<Rhs: ?Sized = Self> {
/// Tests for `self` and `other` values to be equal, and is used by `==`.
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-12-22 10:14:11 +00:00
#[rustc_diagnostic_item = "cmp_partialeq_eq"]
fn eq(&self, other: &Rhs) -> bool;
2014-10-30 01:11:16 +00:00
/// Tests for `!=`. The default implementation is almost always sufficient,
/// and should not be overridden without very good reason.
2014-10-30 01:11:16 +00:00
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-12-22 10:14:11 +00:00
#[rustc_diagnostic_item = "cmp_partialeq_ne"]
fn ne(&self, other: &Rhs) -> bool {
!self.eq(other)
}
2014-10-30 01:11:16 +00:00
}
/// Derive macro generating an impl of the trait [`PartialEq`].
/// The behavior of this macro is described in detail [here](PartialEq#derivable).
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
Migrate from `#[structural_match]` attribute a lang-item trait. (Or more precisely, a pair of such traits: one for `derive(PartialEq)` and one for `derive(Eq)`.) ((The addition of the second marker trait, `StructuralEq`, is largely a hack to work-around `fn (&T)` not implementing `PartialEq` and `Eq`; see also issue rust-lang/rust#46989; otherwise I would just check if `Eq` is implemented.)) Note: this does not use trait fulfillment error-reporting machinery; it just uses the trait system to determine if the ADT was tagged or not. (Nonetheless, I have kept an `on_unimplemented` message on the new trait for structural_match check, even though it is currently not used.) Note also: this does *not* resolve the ICE from rust-lang/rust#65466, as noted in a comment added in this commit. Further work is necessary to resolve that and other problems with the structural match checking, especially to do so without breaking stable code (adapted from test fn-ptr-is-structurally-matchable.rs): ```rust fn r_sm_to(_: &SM) {} fn main() { const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to); let input: Wrap<fn(&SM)> = Wrap(r_sm_to); match Wrap(input) { Wrap(CFN6) => {} Wrap(_) => {} }; } ``` where we would hit a problem with the strategy of unconditionally checking for `PartialEq` because the type `for <'a> fn(&'a SM)` does not currently even *implement* `PartialEq`. ---- added review feedback: * use an or-pattern * eschew `return` when tail position will do. * don't need fresh_expansion; just add `structural_match` to appropriate `allow_internal_unstable` attributes. also fixed example in doc comment so that it actually compiles.
2019-10-17 08:54:37 +00:00
#[allow_internal_unstable(core_intrinsics, structural_match)]
pub macro PartialEq($item:item) {
/* compiler built-in */
}
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
/// Trait for comparisons corresponding to [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
/// The primary difference to [`PartialEq`] is the additional requirement for reflexivity. A type
/// that implements [`PartialEq`] guarantees that for all `a`, `b` and `c`:
///
2024-09-27 08:26:02 +00:00
/// - symmetric: `a == b` implies `b == a` and `a != b` implies `!(a == b)`
/// - transitive: `a == b` and `b == c` implies `a == c`
2015-02-06 02:57:55 +00:00
///
2024-08-26 09:59:00 +00:00
/// `Eq`, which builds on top of [`PartialEq`] also implies:
///
/// - reflexive: `a == a`
///
2024-08-26 09:59:00 +00:00
/// This property cannot be checked by the compiler, and therefore `Eq` is a trait without methods.
///
/// Violating this property is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
/// Floating point types such as [`f32`] and [`f64`] implement only [`PartialEq`] but *not* `Eq`
/// because `NaN` != `NaN`.
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has no extra methods, it
/// is only informing the compiler that this is an equivalence relation rather than a partial
/// equivalence relation. Note that the `derive` strategy requires all fields are `Eq`, which isn't
/// always desired.
///
/// ## How can I implement `Eq`?
///
/// If you cannot use the `derive` strategy, specify that your type implements `Eq`, which has no
/// extra methods:
///
/// ```
/// enum BookFormat {
/// Paperback,
/// Hardback,
/// Ebook,
/// }
///
/// struct Book {
/// isbn: i32,
/// format: BookFormat,
/// }
///
/// impl PartialEq for Book {
/// fn eq(&self, other: &Self) -> bool {
/// self.isbn == other.isbn
/// }
/// }
///
/// impl Eq for Book {}
/// ```
2018-04-25 18:10:58 +00:00
#[doc(alias = "==")]
#[doc(alias = "!=")]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Eq"]
2015-01-05 02:39:02 +00:00
pub trait Eq: PartialEq<Self> {
2024-09-27 08:26:02 +00:00
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
// without using a method on this trait is nearly impossible.
2014-10-30 01:11:16 +00:00
//
// This should never be implemented by hand.
#[doc(hidden)]
2023-10-04 02:27:25 +00:00
#[coverage(off)]
#[inline]
2015-02-17 23:24:34 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2014-10-30 01:11:16 +00:00
fn assert_receiver_is_total_eq(&self) {}
}
/// Derive macro generating an impl of the trait [`Eq`].
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
2023-08-09 14:57:16 +00:00
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
#[allow_internal_unstable(coverage_attribute)]
pub macro Eq($item:item) {
/* compiler built-in */
}
2016-08-26 16:23:42 +00:00
// FIXME: this struct is used solely by #[derive] to
// assert that every component of a type implements Eq.
//
// This struct should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_eq", reason = "deriving hack, should not be public", issue = "none")]
2019-04-15 02:23:21 +00:00
pub struct AssertParamIsEq<T: Eq + ?Sized> {
_field: crate::marker::PhantomData<T>,
}
2016-08-26 16:23:42 +00:00
2015-02-06 02:57:55 +00:00
/// An `Ordering` is the result of a comparison between two values.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(1.cmp(&2), Ordering::Less);
2015-02-06 02:57:55 +00:00
///
/// assert_eq!(1.cmp(&1), Ordering::Equal);
2015-02-06 02:57:55 +00:00
///
/// assert_eq!(2.cmp(&1), Ordering::Greater);
2015-02-06 02:57:55 +00:00
/// ```
2023-04-16 06:49:27 +00:00
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-03-25 00:13:26 +00:00
// This is a lang item only so that `BinOp::Cmp` in MIR can return it.
// It has no special behavior, but does require that the three variants
2024-03-25 00:13:26 +00:00
// `Less`/`Equal`/`Greater` remain `-1_i8`/`0_i8`/`+1_i8` respectively.
2024-04-29 13:27:34 +00:00
#[lang = "Ordering"]
#[repr(i8)]
pub enum Ordering {
/// An ordering where a compared value is less than another.
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
Less = -1,
/// An ordering where a compared value is equal to another.
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
Equal = 0,
/// An ordering where a compared value is greater than another.
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
Greater = 1,
}
2013-03-02 03:07:12 +00:00
impl Ordering {
/// Returns `true` if the ordering is the `Equal` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_eq(), false);
/// assert_eq!(Ordering::Equal.is_eq(), true);
/// assert_eq!(Ordering::Greater.is_eq(), false);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_eq(self) -> bool {
matches!(self, Equal)
}
/// Returns `true` if the ordering is not the `Equal` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_ne(), true);
/// assert_eq!(Ordering::Equal.is_ne(), false);
/// assert_eq!(Ordering::Greater.is_ne(), true);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_ne(self) -> bool {
!matches!(self, Equal)
}
/// Returns `true` if the ordering is the `Less` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_lt(), true);
/// assert_eq!(Ordering::Equal.is_lt(), false);
/// assert_eq!(Ordering::Greater.is_lt(), false);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_lt(self) -> bool {
matches!(self, Less)
}
/// Returns `true` if the ordering is the `Greater` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_gt(), false);
/// assert_eq!(Ordering::Equal.is_gt(), false);
/// assert_eq!(Ordering::Greater.is_gt(), true);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_gt(self) -> bool {
matches!(self, Greater)
}
/// Returns `true` if the ordering is either the `Less` or `Equal` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_le(), true);
/// assert_eq!(Ordering::Equal.is_le(), true);
/// assert_eq!(Ordering::Greater.is_le(), false);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_le(self) -> bool {
!matches!(self, Greater)
}
/// Returns `true` if the ordering is either the `Greater` or `Equal` variant.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_ge(), false);
/// assert_eq!(Ordering::Equal.is_ge(), true);
/// assert_eq!(Ordering::Greater.is_ge(), true);
/// ```
#[inline]
#[must_use]
2021-04-24 16:45:20 +00:00
#[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
#[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_ge(self) -> bool {
!matches!(self, Less)
}
/// Reverses the `Ordering`.
///
2015-02-06 02:57:55 +00:00
/// * `Less` becomes `Greater`.
/// * `Greater` becomes `Less`.
/// * `Equal` becomes `Equal`.
///
2015-02-06 02:57:55 +00:00
/// # Examples
///
2015-02-06 02:57:55 +00:00
/// Basic behavior:
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.reverse(), Ordering::Greater);
/// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal);
/// assert_eq!(Ordering::Greater.reverse(), Ordering::Less);
/// ```
///
/// This method can be used to reverse a comparison:
///
/// ```
/// let data: &mut [_] = &mut [2, 10, 5, 8];
///
/// // sort the array from largest to smallest.
/// data.sort_by(|a, b| a.cmp(b).reverse());
///
/// let b: &mut [_] = &mut [10, 8, 5, 2];
2014-08-06 09:59:40 +00:00
/// assert!(data == b);
/// ```
#[inline]
#[must_use]
#[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
pub const fn reverse(self) -> Ordering {
match self {
Less => Greater,
Equal => Equal,
Greater => Less,
}
}
2016-10-09 08:46:11 +00:00
2016-10-10 16:54:37 +00:00
/// Chains two orderings.
2016-10-09 12:10:56 +00:00
///
2016-10-09 08:46:11 +00:00
/// Returns `self` when it's not `Equal`. Otherwise returns `other`.
2020-01-29 12:32:37 +00:00
///
2016-10-09 08:46:11 +00:00
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Equal.then(Ordering::Less);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Less.then(Ordering::Equal);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Less.then(Ordering::Greater);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Equal.then(Ordering::Equal);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Equal);
///
2016-10-16 18:24:20 +00:00
/// let x: (i64, i64, i64) = (1, 2, 7);
/// let y: (i64, i64, i64) = (1, 5, 3);
2016-10-27 21:31:10 +00:00
/// let result = x.0.cmp(&y.0).then(x.1.cmp(&y.1)).then(x.2.cmp(&y.2));
2016-10-09 08:46:11 +00:00
///
/// assert_eq!(result, Ordering::Less);
/// ```
#[inline]
#[must_use]
#[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
#[stable(feature = "ordering_chaining", since = "1.17.0")]
pub const fn then(self, other: Ordering) -> Ordering {
2016-10-09 08:46:11 +00:00
match self {
Equal => other,
_ => self,
}
}
2016-10-10 16:54:37 +00:00
/// Chains the ordering with the given function.
2016-10-09 12:10:56 +00:00
///
2016-10-09 08:46:11 +00:00
/// Returns `self` when it's not `Equal`. Otherwise calls `f` and returns
/// the result.
2016-10-09 12:10:56 +00:00
///
2016-10-09 08:46:11 +00:00
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Equal.then_with(|| Ordering::Less);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Less.then_with(|| Ordering::Equal);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Less.then_with(|| Ordering::Greater);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Less);
///
2016-10-27 21:31:10 +00:00
/// let result = Ordering::Equal.then_with(|| Ordering::Equal);
2016-10-09 08:46:11 +00:00
/// assert_eq!(result, Ordering::Equal);
///
2016-10-16 18:24:20 +00:00
/// let x: (i64, i64, i64) = (1, 2, 7);
2021-01-17 15:11:48 +00:00
/// let y: (i64, i64, i64) = (1, 5, 3);
2016-10-27 21:31:10 +00:00
/// let result = x.0.cmp(&y.0).then_with(|| x.1.cmp(&y.1)).then_with(|| x.2.cmp(&y.2));
2016-10-09 08:46:11 +00:00
///
/// assert_eq!(result, Ordering::Less);
/// ```
#[inline]
#[must_use]
#[stable(feature = "ordering_chaining", since = "1.17.0")]
2016-10-27 21:31:10 +00:00
pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
2016-10-09 08:46:11 +00:00
match self {
Equal => f(),
_ => self,
}
}
}
/// A helper struct for reverse ordering.
///
2020-01-29 12:32:37 +00:00
/// This struct is a helper to be used with functions like [`Vec::sort_by_key`] and
/// can be used to reverse order a part of a key.
///
2020-01-29 12:32:37 +00:00
/// [`Vec::sort_by_key`]: ../../std/vec/struct.Vec.html#method.sort_by_key
///
/// # Examples
///
/// ```
/// use std::cmp::Reverse;
///
/// let mut v = vec![1, 2, 3, 4, 5, 6];
2017-03-22 08:04:42 +00:00
/// v.sort_by_key(|&num| (num > 3, Reverse(num)));
/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
/// ```
2021-05-11 11:00:34 +00:00
#[derive(PartialEq, Eq, Debug, Copy, Default, Hash)]
2017-06-08 15:34:22 +00:00
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
#[repr(transparent)]
pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
2017-06-08 15:34:22 +00:00
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
2023-04-16 06:49:27 +00:00
impl<T: PartialOrd> PartialOrd for Reverse<T> {
#[inline]
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
other.0.partial_cmp(&self.0)
}
#[inline]
fn lt(&self, other: &Self) -> bool {
other.0 < self.0
}
#[inline]
fn le(&self, other: &Self) -> bool {
other.0 <= self.0
}
#[inline]
fn gt(&self, other: &Self) -> bool {
other.0 > self.0
}
#[inline]
fn ge(&self, other: &Self) -> bool {
other.0 >= self.0
}
}
2017-06-08 15:34:22 +00:00
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
2017-03-22 13:16:41 +00:00
impl<T: Ord> Ord for Reverse<T> {
#[inline]
fn cmp(&self, other: &Reverse<T>) -> Ordering {
other.0.cmp(&self.0)
}
}
2021-05-11 11:00:34 +00:00
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
impl<T: Clone> Clone for Reverse<T> {
#[inline]
fn clone(&self) -> Reverse<T> {
Reverse(self.0.clone())
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0)
2021-05-11 11:00:34 +00:00
}
}
2015-02-06 02:57:55 +00:00
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure `max`,
/// `min`, and `clamp` are consistent with `cmp`:
///
/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp) (ensured by the default
/// implementation).
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
/// ## Corollaries
///
/// From the above and the requirements of `PartialOrd`, it follows that for all `a`, `b` and `c`:
///
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and
/// `>`.
///
/// Mathematically speaking, the `<` operator defines a strict [weak order]. In cases where `==`
/// conforms to mathematical equality, it also defines a strict [total order].
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
///
/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
/// [total order]: https://en.wikipedia.org/wiki/Total_order
///
/// ## Derivable
///
/// This trait can be used with `#[derive]`.
///
/// When `derive`d on structs, it will produce a
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
/// top-to-bottom declaration order of the struct's members.
///
/// When `derive`d on enums, variants are ordered primarily by their discriminants. Secondarily,
/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
/// top, and largest for variants at the bottom. Here's an example:
///
/// ```
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
/// enum E {
/// Top,
/// Bottom,
/// }
///
/// assert!(E::Top < E::Bottom);
/// ```
///
/// However, manually setting the discriminants can override this default behavior:
2022-01-16 04:44:47 +00:00
///
/// ```
2022-01-16 00:25:09 +00:00
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
/// enum E {
/// Top = 2,
/// Bottom = 1,
/// }
///
/// assert!(E::Bottom < E::Top);
/// ```
///
/// ## Lexicographical comparison
///
/// Lexicographical comparison is an operation with the following properties:
/// - Two sequences are compared element by element.
/// - The first mismatching element defines which sequence is lexicographically less or greater
/// than the other.
/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than
/// the other.
/// - If two sequences have equivalent elements and are of the same length, then the sequences are
/// lexicographically equal.
/// - An empty sequence is lexicographically less than any non-empty sequence.
/// - Two empty sequences are lexicographically equal.
///
/// ## How can I implement `Ord`?
///
2024-09-29 07:32:03 +00:00
/// `Ord` requires that the type also be [`PartialOrd`], [`PartialEq`], and [`Eq`].
2024-09-27 08:26:02 +00:00
///
/// Because `Ord` implies a stronger ordering relationship than [`PartialOrd`], and both `Ord` and
/// [`PartialOrd`] must agree, you must choose how to implement `Ord` **first**. You can choose to
/// derive it, or implement it manually. If you derive it, you should derive all four traits. If you
/// implement it manually, you should manually implement all four traits, based on the
/// implementation of `Ord`.
///
/// Here's an example where you want to define the `Character` comparison by `health` and
/// `experience` only, disregarding the field `mana`:
///
/// ```
/// use std::cmp::Ordering;
///
/// struct Character {
/// health: u32,
/// experience: u32,
/// mana: f32,
/// }
///
/// impl Ord for Character {
/// fn cmp(&self, other: &Self) -> Ordering {
2024-08-26 09:59:00 +00:00
/// self.experience
/// .cmp(&other.experience)
/// .then(self.health.cmp(&other.health))
/// }
/// }
///
/// impl PartialOrd for Character {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.cmp(other))
/// }
/// }
///
/// impl PartialEq for Character {
/// fn eq(&self, other: &Self) -> bool {
/// self.health == other.health && self.experience == other.experience
/// }
/// }
///
/// impl Eq for Character {}
/// ```
2020-01-29 12:32:37 +00:00
///
/// If all you need is to `slice::sort` a type by a field value, it can be simpler to use
/// `slice::sort_by_key`.
///
/// ## Examples of incorrect `Ord` implementations
///
/// ```
/// use std::cmp::Ordering;
///
/// #[derive(Debug)]
/// struct Character {
/// health: f32,
/// }
///
/// impl Ord for Character {
/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
/// if self.health < other.health {
/// Ordering::Less
/// } else if self.health > other.health {
/// Ordering::Greater
/// } else {
/// Ordering::Equal
/// }
/// }
/// }
///
/// impl PartialOrd for Character {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.cmp(other))
/// }
/// }
///
/// impl PartialEq for Character {
/// fn eq(&self, other: &Self) -> bool {
/// self.health == other.health
/// }
/// }
///
/// impl Eq for Character {}
///
/// let a = Character { health: 4.5 };
/// let b = Character { health: f32::NAN };
///
/// // Mistake: floating-point values do not form a total order and using the built-in comparison
/// // operands to implement `Ord` irregardless of that reality does not change it. Use
/// // `f32::total_cmp` if you need a total order for floating-point values.
///
/// // Reflexivity requirement of `Ord` is not given.
/// assert!(a == a);
/// assert!(b != b);
///
/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
/// // true, not both or neither.
/// assert_eq!((a < b) as u8 + (b < a) as u8, 0);
/// ```
///
/// ```
/// use std::cmp::Ordering;
///
2024-09-27 08:26:02 +00:00
/// #[derive(Debug)]
/// struct Character {
/// health: u32,
/// experience: u32,
/// }
///
/// impl PartialOrd for Character {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.cmp(other))
/// }
/// }
///
/// impl Ord for Character {
/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
/// if self.health < 50 {
/// self.health.cmp(&other.health)
/// } else {
/// self.experience.cmp(&other.experience)
/// }
/// }
/// }
///
/// // For performance reasons implementing `PartialEq` this way is not the idiomatic way, but it
/// // ensures consistent behavior between `PartialEq`, `PartialOrd` and `Ord` in this example.
/// impl PartialEq for Character {
/// fn eq(&self, other: &Self) -> bool {
/// self.cmp(other) == Ordering::Equal
/// }
/// }
///
2024-09-27 08:26:02 +00:00
/// impl Eq for Character {}
///
/// let a = Character {
/// health: 3,
/// experience: 5,
/// };
/// let b = Character {
/// health: 10,
/// experience: 77,
/// };
/// let c = Character {
/// health: 143,
/// experience: 2,
/// };
///
/// // Mistake: The implementation of `Ord` compares different fields depending on the value of
/// // `self.health`, the resulting order is not total.
///
/// // Transitivity requirement of `Ord` is not given. If a is smaller than b and b is smaller than
/// // c, by transitive property a must also be smaller than c.
/// assert!(a < b && b < c && c < a);
///
/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
/// // true, not both or neither.
2024-08-12 12:46:11 +00:00
/// assert_eq!((a < c) as u8 + (c < a) as u8, 2);
/// ```
///
/// The documentation of [`PartialOrd`] contains further examples, for example it's wrong for
/// [`PartialOrd`] and [`PartialEq`] to disagree.
///
2020-01-29 12:32:37 +00:00
/// [`cmp`]: Ord::cmp
2018-04-25 18:10:58 +00:00
#[doc(alias = "<")]
#[doc(alias = ">")]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Ord"]
2015-01-05 02:39:02 +00:00
pub trait Ord: Eq + PartialOrd<Self> {
2020-01-29 12:32:37 +00:00
/// This method returns an [`Ordering`] between `self` and `other`.
2015-02-06 02:57:55 +00:00
///
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
/// `self <operator> other` if true.
2014-10-30 01:11:16 +00:00
///
2015-02-06 02:57:55 +00:00
/// # Examples
2014-10-30 01:11:16 +00:00
///
/// ```
2015-02-06 02:57:55 +00:00
/// use std::cmp::Ordering;
///
2015-02-06 02:57:55 +00:00
/// assert_eq!(5.cmp(&10), Ordering::Less);
/// assert_eq!(10.cmp(&5), Ordering::Greater);
/// assert_eq!(5.cmp(&5), Ordering::Equal);
2014-10-30 01:11:16 +00:00
/// ```
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-09-27 03:56:38 +00:00
#[rustc_diagnostic_item = "ord_cmp_method"]
fn cmp(&self, other: &Self) -> Ordering;
/// Compares and returns the maximum of two values.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// assert_eq!(1.max(2), 2);
/// assert_eq!(2.max(2), 2);
/// ```
#[stable(feature = "ord_max_min", since = "1.21.0")]
2018-08-09 09:27:48 +00:00
#[inline]
#[must_use]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_ord_max"]
fn max(self, other: Self) -> Self
where
Self: Sized,
{
2023-01-25 14:48:32 +00:00
max_by(self, other, Ord::cmp)
}
/// Compares and returns the minimum of two values.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// assert_eq!(1.min(2), 1);
/// assert_eq!(2.min(2), 2);
/// ```
#[stable(feature = "ord_max_min", since = "1.21.0")]
2018-08-09 09:27:48 +00:00
#[inline]
#[must_use]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_ord_min"]
fn min(self, other: Self) -> Self
where
Self: Sized,
{
2023-01-25 14:48:32 +00:00
min_by(self, other, Ord::cmp)
}
2019-03-09 18:16:54 +00:00
/// Restrict a value to a certain interval.
///
/// Returns `max` if `self` is greater than `max`, and `min` if `self` is
/// less than `min`. Otherwise this returns `self`.
///
/// # Panics
///
/// Panics if `min > max`.
2019-03-09 18:16:54 +00:00
///
/// # Examples
///
/// ```
/// assert_eq!((-3).clamp(-2, 1), -2);
/// assert_eq!(0.clamp(-2, 1), 0);
/// assert_eq!(2.clamp(-2, 1), 1);
2019-03-09 18:16:54 +00:00
/// ```
#[must_use]
2024-05-23 16:45:03 +00:00
#[inline]
#[stable(feature = "clamp", since = "1.50.0")]
2019-03-09 18:16:54 +00:00
fn clamp(self, min: Self, max: Self) -> Self
where
Self: Sized,
{
assert!(min <= max);
if self < min {
min
} else if self > max {
2019-03-09 18:16:54 +00:00
max
} else {
self
}
}
2014-10-30 01:11:16 +00:00
}
/// Derive macro generating an impl of the trait [`Ord`].
/// The behavior of this macro is described in detail [here](Ord#derivable).
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro Ord($item:item) {
/* compiler built-in */
}
/// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order).
///
/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using the `<`, `<=`, `>`, and
/// `>=` operators, respectively.
///
/// This trait should **only** contain the comparison logic for a type **if one plans on only
/// implementing `PartialOrd` but not [`Ord`]**. Otherwise the comparison logic should be in [`Ord`]
/// and this trait implemented with `Some(self.cmp(other))`.
///
/// The methods of this trait must be consistent with each other and with those of [`PartialEq`].
/// The following conditions must hold:
///
/// 1. `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
/// 2. `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
/// 3. `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
2024-08-26 09:59:00 +00:00
/// 4. `a <= b` if and only if `a < b || a == b`
/// 5. `a >= b` if and only if `a > b || a == b`
/// 6. `a != b` if and only if `!(a == b)`.
///
/// Conditions 25 above are ensured by the default implementation. Condition 6 is already ensured
/// by [`PartialEq`].
///
/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's easy to
/// accidentally make them disagree by deriving some of the traits and manually implementing others.
///
/// The comparison relations must satisfy the following conditions (for all `a`, `b`, `c` of type
/// `A`, `B`, `C`):
///
/// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A: PartialOrd<C>`, then `a
/// < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. This must also
/// work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`, `C:
/// PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
/// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b >
/// a`.
///
/// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>` (transitive) impls are not forced
/// to exist, but these requirements apply whenever they do exist.
///
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
/// specified, but users of the trait must ensure that such logic errors do *not* result in
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
/// ## Cross-crate considerations
///
/// Upholding the requirements stated above can become tricky when one crate implements `PartialOrd`
/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the
/// standard library). The recommendation is to never implement this trait for a foreign type. In
/// other words, such a crate should do `impl PartialOrd<ForeignType> for LocalType`, but it should
/// *not* do `impl PartialOrd<LocalType> for ForeignType`.
///
/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local
/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T < U`. In
/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ...
/// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate
/// defining `T` already knows about. This rules out transitive chains where downstream crates can
/// add new `impl`s that "stitch together" comparisons of foreign types in ways that violate
/// transitivity.
///
/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding
/// more `PartialOrd` implementations can cause build failures in downstream crates.
///
/// ## Corollaries
///
/// The following corollaries follow from the above requirements:
///
/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
///
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
/// ## Strict and non-strict partial orders
///
/// The `<` and `>` operators behave according to a *strict* partial order. However, `<=` and `>=`
/// do **not** behave according to a *non-strict* partial order. That is because mathematically, a
/// non-strict partial order would require reflexivity, i.e. `a <= a` would need to be true for
/// every `a`. This isn't always the case for types that implement `PartialOrd`, for example:
docs: Correct terminology in std::cmp Some clarifications regarding used (mathematical) terminology: * Avoid using the terms "total equality" and "partial equality" in favor of "equivalence relation" and "partial equivalence relation", which are well-defined and unambiguous. * Clarify that `Ordering` is an ordering between two values (and not an order in the mathematical sense). * Avoid saying that `PartialEq` and `Eq` are "equality comparisons" because the terminology "equality comparison" could be misleading: it's possible to implement `PartialEq` and `Eq` for other (partial) equivalence relations, in particular for relations where `a == b` for some `a` and `b` even when `a` and `b` are not the same value. * Added a section "Strict and non-strict partial orders" to document that the `<=` and `>=` operators do not correspond to non-strict partial orders. * Corrected section "Corollaries" in documenation of Ord in regard to `<` only describing a strict total order in cases where `==` conforms to mathematical equality. Made documentation easier to understand: * Explicitly state at the beginning of `PartialEq`'s documentation comment that implementing the trait will provide the `==` and `!=` operators. * Added an easier to understand rule when to implement `Eq` in addition to `PartialEq`: "if it’s guaranteed that `PartialEq::eq(a, a)` always returns `true`." * Explicitly mention in documentation of `Eq` that the properties "symmetric" and "transitive" are already required by `PartialEq`.
2023-07-26 17:36:26 +00:00
///
/// ```
/// let a = f64::sqrt(-1.0);
/// assert_eq!(a <= a, false);
/// ```
///
/// ## Derivable
///
/// This trait can be used with `#[derive]`.
///
/// When `derive`d on structs, it will produce a
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
/// top-to-bottom declaration order of the struct's members.
///
/// When `derive`d on enums, variants are primarily ordered by their discriminants. Secondarily,
/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
/// top, and largest for variants at the bottom. Here's an example:
///
/// ```
/// #[derive(PartialEq, PartialOrd)]
/// enum E {
/// Top,
/// Bottom,
/// }
///
/// assert!(E::Top < E::Bottom);
/// ```
2022-01-16 00:25:09 +00:00
///
/// However, manually setting the discriminants can override this default behavior:
2022-01-16 04:44:47 +00:00
///
2022-01-16 00:25:09 +00:00
/// ```
/// #[derive(PartialEq, PartialOrd)]
/// enum E {
/// Top = 2,
/// Bottom = 1,
2022-01-16 00:25:09 +00:00
/// }
///
/// assert!(E::Bottom < E::Top);
2022-01-16 00:25:09 +00:00
/// ```
///
2016-12-29 22:21:07 +00:00
/// ## How can I implement `PartialOrd`?
///
2020-01-29 12:32:37 +00:00
/// `PartialOrd` only requires implementation of the [`partial_cmp`] method, with the others
/// generated from default implementations.
///
2015-02-06 02:57:55 +00:00
/// However it remains possible to implement the others separately for types which do not have a
/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == false`
/// (cf. IEEE 754-2008 section 5.11).
///
2020-01-29 12:32:37 +00:00
/// `PartialOrd` requires your type to be [`PartialEq`].
///
2020-01-29 12:32:37 +00:00
/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
///
/// ```
/// use std::cmp::Ordering;
///
/// struct Person {
/// id: u32,
/// name: String,
/// height: u32,
/// }
///
/// impl PartialOrd for Person {
2020-09-22 21:36:08 +00:00
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.cmp(other))
/// }
/// }
///
/// impl Ord for Person {
2020-09-22 21:36:08 +00:00
/// fn cmp(&self, other: &Self) -> Ordering {
/// self.height.cmp(&other.height)
/// }
/// }
///
/// impl PartialEq for Person {
2020-09-22 21:36:08 +00:00
/// fn eq(&self, other: &Self) -> bool {
/// self.height == other.height
/// }
/// }
2024-09-27 08:26:02 +00:00
///
/// impl Eq for Person {}
/// ```
///
/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here is an example of
/// `Person` types who have a floating-point `height` field that is the only field to be used for
/// sorting:
///
/// ```
/// use std::cmp::Ordering;
///
/// struct Person {
/// id: u32,
/// name: String,
/// height: f64,
/// }
///
/// impl PartialOrd for Person {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// self.height.partial_cmp(&other.height)
/// }
/// }
///
/// impl PartialEq for Person {
/// fn eq(&self, other: &Self) -> bool {
/// self.height == other.height
/// }
/// }
/// ```
2016-03-14 15:43:55 +00:00
///
/// ## Examples of incorrect `PartialOrd` implementations
///
/// ```
/// use std::cmp::Ordering;
///
/// #[derive(PartialEq, Debug)]
/// struct Character {
/// health: u32,
/// experience: u32,
/// }
///
/// impl PartialOrd for Character {
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
/// Some(self.health.cmp(&other.health))
/// }
/// }
///
/// let a = Character {
/// health: 10,
/// experience: 5,
/// };
/// let b = Character {
/// health: 10,
/// experience: 77,
/// };
///
/// // Mistake: `PartialEq` and `PartialOrd` disagree with each other.
///
/// assert_eq!(a.partial_cmp(&b).unwrap(), Ordering::Equal); // a == b according to `PartialOrd`.
/// assert_ne!(a, b); // a != b according to `PartialEq`.
/// ```
///
2016-03-14 15:43:55 +00:00
/// # Examples
///
/// ```
2022-01-16 00:25:09 +00:00
/// let x: u32 = 0;
/// let y: u32 = 1;
2016-03-14 15:43:55 +00:00
///
/// assert_eq!(x < y, true);
/// assert_eq!(x.lt(&y), true);
/// ```
2020-01-29 12:32:37 +00:00
///
/// [`partial_cmp`]: PartialOrd::partial_cmp
/// [`cmp`]: Ord::cmp
#[lang = "partial_ord"]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2018-04-25 18:10:58 +00:00
#[doc(alias = ">")]
#[doc(alias = "<")]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
2022-08-28 06:27:15 +00:00
#[rustc_on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
append_const_msg
)]
#[rustc_diagnostic_item = "PartialOrd"]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
2015-02-06 02:57:55 +00:00
/// This method returns an ordering between `self` and `other` values if one exists.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// let result = 1.0.partial_cmp(&2.0);
/// assert_eq!(result, Some(Ordering::Less));
///
/// let result = 1.0.partial_cmp(&1.0);
/// assert_eq!(result, Some(Ordering::Equal));
///
/// let result = 2.0.partial_cmp(&1.0);
/// assert_eq!(result, Some(Ordering::Greater));
/// ```
///
/// When comparison is impossible:
///
/// ```
/// let result = f64::NAN.partial_cmp(&1.0);
2015-02-06 02:57:55 +00:00
/// assert_eq!(result, None);
/// ```
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_partialord_cmp"]
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
2014-10-30 01:11:16 +00:00
/// Tests less than (for `self` and `other`) and is used by the `<` operator.
2015-02-06 02:57:55 +00:00
///
/// # Examples
///
/// ```
/// assert_eq!(1.0 < 1.0, false);
/// assert_eq!(1.0 < 2.0, true);
/// assert_eq!(2.0 < 1.0, false);
2015-02-06 02:57:55 +00:00
/// ```
2014-10-30 01:11:16 +00:00
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_partialord_lt"]
fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less))
2014-10-30 01:11:16 +00:00
}
/// Tests less than or equal to (for `self` and `other`) and is used by the
/// `<=` operator.
2015-02-06 02:57:55 +00:00
///
/// # Examples
///
/// ```
/// assert_eq!(1.0 <= 1.0, true);
/// assert_eq!(1.0 <= 2.0, true);
/// assert_eq!(2.0 <= 1.0, false);
2015-02-06 02:57:55 +00:00
/// ```
2014-10-30 01:11:16 +00:00
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_partialord_le"]
fn le(&self, other: &Rhs) -> bool {
2022-08-12 17:22:38 +00:00
matches!(self.partial_cmp(other), Some(Less | Equal))
2014-10-30 01:11:16 +00:00
}
/// Tests greater than (for `self` and `other`) and is used by the `>`
/// operator.
2015-02-06 02:57:55 +00:00
///
/// # Examples
///
/// ```
/// assert_eq!(1.0 > 1.0, false);
/// assert_eq!(1.0 > 2.0, false);
/// assert_eq!(2.0 > 1.0, true);
2015-02-06 02:57:55 +00:00
/// ```
2014-10-30 01:11:16 +00:00
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_partialord_gt"]
fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater))
2014-10-30 01:11:16 +00:00
}
/// Tests greater than or equal to (for `self` and `other`) and is used by
/// the `>=` operator.
2015-02-06 02:57:55 +00:00
///
/// # Examples
///
/// ```
/// assert_eq!(1.0 >= 1.0, true);
/// assert_eq!(1.0 >= 2.0, false);
/// assert_eq!(2.0 >= 1.0, true);
2015-02-06 02:57:55 +00:00
/// ```
2014-10-30 01:11:16 +00:00
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2024-04-29 13:27:34 +00:00
#[rustc_diagnostic_item = "cmp_partialord_ge"]
fn ge(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater | Equal))
2014-10-30 01:11:16 +00:00
}
}
/// Derive macro generating an impl of the trait [`PartialOrd`].
/// The behavior of this macro is described in detail [here](PartialOrd#derivable).
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
pub macro PartialOrd($item:item) {
/* compiler built-in */
}
/// Compares and returns the minimum of two values.
2015-02-06 02:57:55 +00:00
///
/// Returns the first argument if the comparison determines them to be equal.
///
2020-01-29 12:32:37 +00:00
/// Internally uses an alias to [`Ord::min`].
///
2015-02-06 02:57:55 +00:00
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(cmp::min(1, 2), 1);
/// assert_eq!(cmp::min(2, 2), 2);
2015-02-06 02:57:55 +00:00
/// ```
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")]
2023-04-16 07:20:26 +00:00
pub fn min<T: Ord>(v1: T, v2: T) -> T {
v1.min(v2)
}
/// Returns the minimum of two values with respect to the specified comparison function.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// let result = cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
/// assert_eq!(result, 1);
///
/// let result = cmp::min_by(-2, 3, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
/// assert_eq!(result, -2);
/// ```
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
2023-04-16 07:20:26 +00:00
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
}
}
/// Returns the element that gives the minimum value from the specified function.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// let result = cmp::min_by_key(-2, 1, |x: &i32| x.abs());
/// assert_eq!(result, 1);
///
/// let result = cmp::min_by_key(-2, 2, |x: &i32| x.abs());
/// assert_eq!(result, -2);
/// ```
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
2023-04-16 07:20:26 +00:00
pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
2023-04-16 06:49:27 +00:00
min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
/// Compares and returns the maximum of two values.
2015-02-06 02:57:55 +00:00
///
/// Returns the second argument if the comparison determines them to be equal.
///
2020-01-29 12:32:37 +00:00
/// Internally uses an alias to [`Ord::max`].
///
2015-02-06 02:57:55 +00:00
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(cmp::max(1, 2), 2);
/// assert_eq!(cmp::max(2, 2), 2);
2015-02-06 02:57:55 +00:00
/// ```
#[inline]
#[must_use]
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")]
2023-04-16 06:49:27 +00:00
pub fn max<T: Ord>(v1: T, v2: T) -> T {
v1.max(v2)
}
2013-03-02 03:07:12 +00:00
/// Returns the maximum of two values with respect to the specified comparison function.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// let result = cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
/// assert_eq!(result, -2);
///
/// let result = cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())) ;
/// assert_eq!(result, 2);
/// ```
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
2023-04-16 07:20:26 +00:00
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
}
}
/// Returns the element that gives the maximum value from the specified function.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// let result = cmp::max_by_key(-2, 1, |x: &i32| x.abs());
/// assert_eq!(result, -2);
///
/// let result = cmp::max_by_key(-2, 2, |x: &i32| x.abs());
/// assert_eq!(result, 2);
/// ```
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
2023-04-16 07:20:26 +00:00
pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
2023-03-20 18:23:03 +00:00
/// Compares and sorts two values, returning minimum and maximum.
///
/// Returns `[v1, v2]` if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_minmax)]
/// use std::cmp;
///
/// assert_eq!(cmp::minmax(1, 2), [1, 2]);
/// assert_eq!(cmp::minmax(2, 2), [2, 2]);
///
/// // You can destructure the result using array patterns
/// let [min, max] = cmp::minmax(42, 17);
/// assert_eq!(min, 17);
/// assert_eq!(max, 42);
/// ```
#[inline]
#[must_use]
#[unstable(feature = "cmp_minmax", issue = "115939")]
2023-03-20 18:23:03 +00:00
pub fn minmax<T>(v1: T, v2: T) -> [T; 2]
where
T: Ord,
{
if v1 <= v2 { [v1, v2] } else { [v2, v1] }
}
/// Returns minimum and maximum values with respect to the specified comparison function.
///
/// Returns `[v1, v2]` if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_minmax)]
/// use std::cmp;
///
/// assert_eq!(cmp::minmax_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [1, -2]);
/// assert_eq!(cmp::minmax_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [-2, 2]);
///
/// // You can destructure the result using array patterns
/// let [min, max] = cmp::minmax_by(-42, 17, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
/// assert_eq!(min, 17);
/// assert_eq!(max, -42);
/// ```
#[inline]
#[must_use]
#[unstable(feature = "cmp_minmax", issue = "115939")]
2023-03-20 18:23:03 +00:00
pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2]
where
F: FnOnce(&T, &T) -> Ordering,
{
if compare(&v1, &v2).is_le() { [v1, v2] } else { [v2, v1] }
}
/// Returns minimum and maximum values with respect to the specified key function.
///
/// Returns `[v1, v2]` if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// #![feature(cmp_minmax)]
/// use std::cmp;
///
/// assert_eq!(cmp::minmax_by_key(-2, 1, |x: &i32| x.abs()), [1, -2]);
/// assert_eq!(cmp::minmax_by_key(-2, 2, |x: &i32| x.abs()), [-2, 2]);
///
/// // You can destructure the result using array patterns
/// let [min, max] = cmp::minmax_by_key(-42, 17, |x: &i32| x.abs());
/// assert_eq!(min, 17);
/// assert_eq!(max, -42);
/// ```
#[inline]
#[must_use]
#[unstable(feature = "cmp_minmax", issue = "115939")]
2023-03-20 18:23:03 +00:00
pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2]
where
F: FnMut(&T) -> K,
K: Ord,
{
minmax_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
mod impls {
2019-04-15 02:23:21 +00:00
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::hint::unreachable_unchecked;
macro_rules! partial_eq_impl {
($($t:ty)*) => ($(
2023-12-06 02:42:59 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for $t {
2023-12-06 02:42:59 +00:00
#[inline]
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
#[inline]
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
}
)*)
}
2014-05-13 04:02:27 +00:00
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl PartialEq for () {
2014-05-13 04:02:27 +00:00
#[inline]
fn eq(&self, _other: &()) -> bool {
true
}
#[inline]
fn ne(&self, _other: &()) -> bool {
false
}
}
partial_eq_impl! {
bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128
}
macro_rules! eq_impl {
($($t:ty)*) => ($(
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for $t {}
)*)
}
eq_impl! { () bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
macro_rules! partial_ord_impl {
($($t:ty)*) => ($(
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl PartialOrd for $t {
#[inline]
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
match (*self <= *other, *self >= *other) {
(false, false) => None,
(false, true) => Some(Greater),
(true, false) => Some(Less),
(true, true) => Some(Equal),
}
}
#[inline(always)]
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
#[inline(always)]
fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
#[inline(always)]
fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
#[inline(always)]
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
}
)*)
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl PartialOrd for () {
2014-05-13 04:02:27 +00:00
#[inline]
fn partial_cmp(&self, _: &()) -> Option<Ordering> {
Some(Equal)
}
2014-05-13 04:02:27 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl PartialOrd for bool {
#[inline]
fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
Some(self.cmp(other))
}
}
partial_ord_impl! { f16 f32 f64 f128 }
macro_rules! ord_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl PartialOrd for $t {
#[inline]
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
2024-04-29 13:27:34 +00:00
Some(crate::intrinsics::three_way_compare(*self, *other))
}
#[inline(always)]
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
#[inline(always)]
fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
#[inline(always)]
fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
#[inline(always)]
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl Ord for $t {
#[inline]
fn cmp(&self, other: &$t) -> Ordering {
2024-04-29 13:27:34 +00:00
crate::intrinsics::three_way_compare(*self, *other)
}
}
)*)
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl Ord for () {
2014-05-13 04:02:27 +00:00
#[inline]
fn cmp(&self, _other: &()) -> Ordering {
Equal
}
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl Ord for bool {
#[inline]
fn cmp(&self, other: &bool) -> Ordering {
// Casting to i8's and converting the difference to an Ordering generates
// more optimal assembly.
// See <https://github.com/rust-lang/rust/issues/66780> for more info.
match (*self as i8) - (*other as i8) {
-1 => Less,
0 => Equal,
1 => Greater,
// SAFETY: bool as i8 returns 0 or 1, so the difference can't be anything else
_ => unsafe { unreachable_unchecked() },
}
}
#[inline]
fn min(self, other: bool) -> bool {
self & other
}
#[inline]
fn max(self, other: bool) -> bool {
self | other
}
#[inline]
fn clamp(self, min: bool, max: bool) -> bool {
assert!(min <= max);
self.max(min).min(max)
}
}
ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
#[unstable(feature = "never_type", issue = "35121")]
2023-04-16 06:49:27 +00:00
impl PartialEq for ! {
#[inline]
2016-08-18 17:08:25 +00:00
fn eq(&self, _: &!) -> bool {
*self
}
}
2016-08-01 04:56:43 +00:00
#[unstable(feature = "never_type", issue = "35121")]
2016-08-18 17:08:25 +00:00
impl Eq for ! {}
2016-08-01 04:56:43 +00:00
#[unstable(feature = "never_type", issue = "35121")]
2023-04-16 06:49:27 +00:00
impl PartialOrd for ! {
#[inline]
2016-08-18 17:08:25 +00:00
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
2016-08-01 04:56:43 +00:00
}
}
#[unstable(feature = "never_type", issue = "35121")]
2023-04-16 06:49:27 +00:00
impl Ord for ! {
#[inline]
2016-08-18 17:08:25 +00:00
fn cmp(&self, _: &!) -> Ordering {
*self
}
}
2016-08-01 04:56:43 +00:00
// & pointers
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
where
2023-04-16 06:49:27 +00:00
A: PartialEq<B>,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
2023-04-16 06:49:27 +00:00
impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
where
2023-04-16 06:49:27 +00:00
A: PartialOrd<B>,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
2014-10-30 01:11:16 +00:00
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&B) -> bool {
PartialOrd::lt(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn le(&self, other: &&B) -> bool {
PartialOrd::le(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn gt(&self, other: &&B) -> bool {
PartialOrd::gt(*self, *other)
}
#[inline]
fn ge(&self, other: &&B) -> bool {
PartialOrd::ge(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &A
where
A: Ord,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Eq for &A where A: Eq {}
2014-10-30 01:11:16 +00:00
// &mut pointers
2014-10-30 01:11:16 +00:00
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A
where
A: PartialEq<B>,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A
where
A: PartialOrd<B>,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
2014-10-30 01:11:16 +00:00
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
fn lt(&self, other: &&mut B) -> bool {
PartialOrd::lt(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn le(&self, other: &&mut B) -> bool {
PartialOrd::le(*self, *other)
}
2014-10-30 01:11:16 +00:00
#[inline]
fn gt(&self, other: &&mut B) -> bool {
PartialOrd::gt(*self, *other)
}
#[inline]
fn ge(&self, other: &&mut B) -> bool {
PartialOrd::ge(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &mut A
where
A: Ord,
{
2014-10-30 01:11:16 +00:00
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(*self, *other)
}
2014-10-30 01:11:16 +00:00
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Eq for &mut A where A: Eq {}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&mut B) -> bool {
PartialEq::eq(*self, *other)
}
#[inline]
fn ne(&self, other: &&mut B) -> bool {
PartialEq::ne(*self, *other)
}
}
2015-01-24 05:48:20 +00:00
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
#[inline]
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
}