@@ -27,12 +27,25 @@ use self::Ordering::*;
2727/// Trait for equality comparisons which are [partial equivalence
2828/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
2929///
30+ /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
31+ /// We use the easier-to-read infix notation in the remainder of this documentation.
32+ ///
3033/// This trait allows for partial equality, for types that do not have a full
3134/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
3235/// so floating point types implement `PartialEq` but not [`trait@Eq`].
3336///
34- /// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
35- /// `C`):
37+ /// Implementations must ensure that `eq` and `ne` are consistent with each other:
38+ ///
39+ /// - `a != b` if and only if `!(a == b)`
40+ /// (ensured by the default implementation).
41+ ///
42+ /// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
43+ /// be consistent with `PartialEq` (see the documentation of those traits for the exact
44+ /// requirememts). It's easy to accidentally make them disagree by deriving some of the traits and
45+ /// manually implementing others.
46+ ///
47+ /// The equality relation `==` must satisfy the following conditions
48+ /// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
3649///
3750/// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
3851/// implies `b == a`**; and
@@ -53,15 +66,6 @@ use self::Ordering::*;
5366///
5467/// ## How can I implement `PartialEq`?
5568///
56- /// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
57- /// in terms of it by default. Any manual implementation of [`ne`] *must* respect
58- /// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
59- /// only if `a != b`.
60- ///
61- /// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
62- /// each other. It's easy to accidentally make them disagree by deriving some
63- /// of the traits and manually implementing others.
64- ///
6569/// An example implementation for a domain in which two books are considered
6670/// the same book if their ISBN matches, even if the formats differ:
6771///
@@ -631,10 +635,25 @@ impl<T: Clone> Clone for Reverse<T> {
631635
632636/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
633637///
634- /// An order is a total order if it is (for all `a`, `b` and `c`):
638+ /// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
639+ /// `max`, `min`, and `clamp` are consistent with `cmp`:
640+ ///
641+ /// - `partial_cmp(a, b) == Some(cmp(a, b))`.
642+ /// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
643+ /// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
644+ /// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
645+ /// (ensured by the default implementation).
646+ ///
647+ /// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
648+ /// deriving some of the traits and manually implementing others.
649+ ///
650+ /// ## Corollaries
651+ ///
652+ /// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
653+ /// This means that for all `a`, `b` and `c`:
635654///
636- /// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
637- /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
655+ /// - exactly one of `a < b`, `a == b` or `a > b` is true; and
656+ /// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
638657///
639658/// ## Derivable
640659///
@@ -659,12 +678,6 @@ impl<T: Clone> Clone for Reverse<T> {
659678/// Then you must define an implementation for [`cmp`]. You may find it useful to use
660679/// [`cmp`] on your type's fields.
661680///
662- /// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
663- /// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
664- /// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
665- /// all `a` and `b`. It's easy to accidentally make them disagree by
666- /// deriving some of the traits and manually implementing others.
667- ///
668681/// Here's an example where you want to sort people by height only, disregarding `id`
669682/// and `name`:
670683///
@@ -824,15 +837,45 @@ impl PartialOrd for Ordering {
824837
825838/// Trait for values that can be compared for a sort-order.
826839///
840+ /// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
841+ /// the `<`, `<=`, `>`, and `>=` operators, respectively.
842+ ///
843+ /// The methods of this trait must be consistent with each other and with those of `PartialEq` in
844+ /// the following sense:
845+ ///
846+ /// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
847+ /// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
848+ /// (ensured by the default implementation).
849+ /// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
850+ /// (ensured by the default implementation).
851+ /// - `a <= b` if and only if `a < b || a == b`
852+ /// (ensured by the default implementation).
853+ /// - `a >= b` if and only if `a > b || a == b`
854+ /// (ensured by the default implementation).
855+ /// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
856+ ///
857+ /// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
858+ /// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
859+ /// easy to accidentally make them disagree by deriving some of the traits and manually
860+ /// implementing others.
861+ ///
827862/// The comparison must satisfy, for all `a`, `b` and `c`:
828863///
829- /// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
830864/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
865+ /// - duality: `a < b` if and only if `b > a`.
831866///
832867/// Note that these requirements mean that the trait itself must be implemented symmetrically and
833868/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
834869/// PartialOrd<V>`.
835870///
871+ /// ## Corollaries
872+ ///
873+ /// The following corollaries follow from the above requirements:
874+ ///
875+ /// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
876+ /// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
877+ /// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
878+ ///
836879/// ## Derivable
837880///
838881/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
@@ -850,10 +893,6 @@ impl PartialOrd for Ordering {
850893///
851894/// `PartialOrd` requires your type to be [`PartialEq`].
852895///
853- /// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
854- /// easy to accidentally make them disagree by deriving some of the traits and manually
855- /// implementing others.
856- ///
857896/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
858897///
859898/// ```
0 commit comments