]> git.lizzy.rs Git - rust.git/blobdiff - library/core/src/cmp.rs
Added diagnostic items to functions for Clippy
[rust.git] / library / core / src / cmp.rs
index ecea898504dc70a7784e7b2d52db991d70d908d7..79610bb409d37c06b383ea7622452560b179ebf6 100644 (file)
 /// Trait for equality comparisons which are [partial equivalence
 /// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
+/// `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.
+///
 /// This trait allows for partial equality, 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, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
-/// `C`):
+/// Implementations must ensure that `eq` and `ne` are consistent with each other:
+///
+/// - `a != b` if and only if `!(a == b)`
+///   (ensured by the default implementation).
+///
+/// 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
+/// 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`):
 ///
 /// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
 ///   implies `b == a`**; and
 ///
 /// ## How can I implement `PartialEq`?
 ///
-/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
-/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
-/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
-/// only if `a != b`.
-///
-/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
-/// each other. It's easy to accidentally make them disagree by deriving some
-/// of the traits and manually implementing others.
-///
 /// An example implementation for a domain in which two books are considered
 /// the same book if their ISBN matches, even if the formats differ:
 ///
@@ -631,10 +635,25 @@ fn clone_from(&mut self, other: &Self) {
 
 /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
 ///
-/// An order is a total order if it is (for all `a`, `b` and `c`):
+/// 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).
+///
+/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
+/// deriving some of the traits and manually implementing others.
+///
+/// ## Corollaries
+///
+/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
+/// This means that for all `a`, `b` and `c`:
 ///
-/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
-/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - 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 `>`.
 ///
 /// ## Derivable
 ///
@@ -659,12 +678,6 @@ fn clone_from(&mut self, other: &Self) {
 /// Then you must define an implementation for [`cmp`]. You may find it useful to use
 /// [`cmp`] on your type's fields.
 ///
-/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
-/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
-/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
-/// all `a` and `b`. It's easy to accidentally make them disagree by
-/// deriving some of the traits and manually implementing others.
-///
 /// Here's an example where you want to sort people by height only, disregarding `id`
 /// and `name`:
 ///
@@ -824,15 +837,45 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 
 /// Trait for values that can be compared for a sort-order.
 ///
+/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
+/// the `<`, `<=`, `>`, and `>=` operators, respectively.
+///
+/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
+/// the following sense:
+///
+/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
+/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
+///   (ensured by the default implementation).
+/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
+///   (ensured by the default implementation).
+/// - `a <= b` if and only if `a < b || a == b`
+///   (ensured by the default implementation).
+/// - `a >= b` if and only if `a > b || a == b`
+///   (ensured by the default implementation).
+/// - `a != b` if and only if `!(a == b)` (already part of `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 must satisfy, for all `a`, `b` and `c`:
 ///
-/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
 /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - duality: `a < b` if and only if `b > a`.
 ///
 /// Note that these requirements mean that the trait itself must be implemented symmetrically and
 /// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
 /// PartialOrd<V>`.
 ///
+/// ## 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)`
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
@@ -850,10 +893,6 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 ///
 /// `PartialOrd` requires your type to be [`PartialEq`].
 ///
-/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
-/// easy to accidentally make them disagree by deriving some of the traits and manually
-/// implementing others.
-///
 /// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
 ///
 /// ```
@@ -1065,6 +1104,7 @@ fn ge(&self, other: &Rhs) -> bool {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")]
 pub fn min<T: Ord>(v1: T, v2: T) -> T {
     v1.min(v2)
 }
@@ -1127,6 +1167,7 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")]
 pub fn max<T: Ord>(v1: T, v2: T) -> T {
     v1.max(v2)
 }