Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c1e54cf

Browse files
authoredSep 29, 2024
Rollup merge of #129003 - Voultapher:improve-ord-docs, r=workingjubilee
Improve Ord docs - Makes wording more clear and re-structures some sections that can be overwhelming for someone not already in the know. - Adds examples of how *not* to implement Ord, inspired by various anti-patterns found in real world code. Many of the wording changes are inspired directly by my personal experience of being confused by the `Ord` docs and seeing other people get it wrong as well, especially lately having looked at a number of `Ord` implementations as part of #128899. Created with help by `@orlp.` r​? `@workingjubilee`
2 parents 1d45203 + a67d3bd commit c1e54cf

File tree

1 file changed

+257
-99
lines changed

1 file changed

+257
-99
lines changed
 

‎library/core/src/cmp.rs

Lines changed: 257 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -275,61 +275,66 @@ pub macro PartialEq($item:item) {
275275
/// Trait for comparisons corresponding to [equivalence relations](
276276
/// https://en.wikipedia.org/wiki/Equivalence_relation).
277277
///
278-
/// This means, that in addition to `a == b` and `a != b` being strict inverses,
279-
/// the relation must be (for all `a`, `b` and `c`):
278+
/// The primary difference to [`PartialEq`] is the additional requirement for reflexivity. A type
279+
/// that implements [`PartialEq`] guarantees that for all `a`, `b` and `c`:
280280
///
281-
/// - reflexive: `a == a`;
282-
/// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as well); and
283-
/// - transitive: `a == b` and `b == c` implies `a == c` (required by `PartialEq` as well).
281+
/// - symmetric: `a == b` implies `b == a` and `a != b` implies `!(a == b)`
282+
/// - transitive: `a == b` and `b == c` implies `a == c`
284283
///
285-
/// This property cannot be checked by the compiler, and therefore `Eq` implies
286-
/// [`PartialEq`], and has no extra methods.
284+
/// `Eq`, which builds on top of [`PartialEq`] also implies:
285+
///
286+
/// - reflexive: `a == a`
287+
///
288+
/// This property cannot be checked by the compiler, and therefore `Eq` is a trait without methods.
287289
///
288290
/// Violating this property is a logic error. The behavior resulting from a logic error is not
289291
/// specified, but users of the trait must ensure that such logic errors do *not* result in
290292
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
291293
/// methods.
292294
///
293-
/// Implement `Eq` in addition to `PartialEq` if it's guaranteed that
294-
/// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in addition to
295-
/// the symmetric and transitive properties already required by `PartialEq`.
295+
/// Floating point types such as [`f32`] and [`f64`] implement only [`PartialEq`] but *not* `Eq`
296+
/// because `NaN` != `NaN`.
296297
///
297298
/// ## Derivable
298299
///
299-
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
300-
/// no extra methods, it is only informing the compiler that this is an
301-
/// equivalence relation rather than a partial equivalence relation. Note that
302-
/// the `derive` strategy requires all fields are `Eq`, which isn't
300+
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has no extra methods, it
301+
/// is only informing the compiler that this is an equivalence relation rather than a partial
302+
/// equivalence relation. Note that the `derive` strategy requires all fields are `Eq`, which isn't
303303
/// always desired.
304304
///
305305
/// ## How can I implement `Eq`?
306306
///
307-
/// If you cannot use the `derive` strategy, specify that your type implements
308-
/// `Eq`, which has no methods:
307+
/// If you cannot use the `derive` strategy, specify that your type implements `Eq`, which has no
308+
/// extra methods:
309309
///
310310
/// ```
311-
/// enum BookFormat { Paperback, Hardback, Ebook }
311+
/// enum BookFormat {
312+
/// Paperback,
313+
/// Hardback,
314+
/// Ebook,
315+
/// }
316+
///
312317
/// struct Book {
313318
/// isbn: i32,
314319
/// format: BookFormat,
315320
/// }
321+
///
316322
/// impl PartialEq for Book {
317323
/// fn eq(&self, other: &Self) -> bool {
318324
/// self.isbn == other.isbn
319325
/// }
320326
/// }
327+
///
321328
/// impl Eq for Book {}
322329
/// ```
323330
#[doc(alias = "==")]
324331
#[doc(alias = "!=")]
325332
#[stable(feature = "rust1", since = "1.0.0")]
326333
#[rustc_diagnostic_item = "Eq"]
327334
pub trait Eq: PartialEq<Self> {
328-
// this method is used solely by #[derive(Eq)] to assert
329-
// that every component of a type implements `Eq`
330-
// itself. The current deriving infrastructure means doing this
331-
// assertion without using a method on this trait is nearly
332-
// impossible.
335+
// this method is used solely by `impl Eq or #[derive(Eq)]` to assert that every component of a
336+
// type implements `Eq` itself. The current deriving infrastructure means doing this assertion
337+
// without using a method on this trait is nearly impossible.
333338
//
334339
// This should never be implemented by hand.
335340
#[doc(hidden)]
@@ -693,17 +698,14 @@ impl<T: Clone> Clone for Reverse<T> {
693698

694699
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
695700
///
696-
/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
697-
/// `max`, `min`, and `clamp` are consistent with `cmp`:
701+
/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure `max`,
702+
/// `min`, and `clamp` are consistent with `cmp`:
698703
///
699704
/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
700705
/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
701706
/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
702-
/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
703-
/// (ensured by the default implementation).
704-
///
705-
/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
706-
/// deriving some of the traits and manually implementing others.
707+
/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp) (ensured by the default
708+
/// implementation).
707709
///
708710
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
709711
/// specified, but users of the trait must ensure that such logic errors do *not* result in
@@ -712,15 +714,14 @@ impl<T: Clone> Clone for Reverse<T> {
712714
///
713715
/// ## Corollaries
714716
///
715-
/// From the above and the requirements of `PartialOrd`, it follows that for
716-
/// all `a`, `b` and `c`:
717+
/// From the above and the requirements of `PartialOrd`, it follows that for all `a`, `b` and `c`:
717718
///
718719
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
719-
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
720+
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and
721+
/// `>`.
720722
///
721-
/// Mathematically speaking, the `<` operator defines a strict [weak order]. In
722-
/// cases where `==` conforms to mathematical equality, it also defines a
723-
/// strict [total order].
723+
/// Mathematically speaking, the `<` operator defines a strict [weak order]. In cases where `==`
724+
/// conforms to mathematical equality, it also defines a strict [total order].
724725
///
725726
/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
726727
/// [total order]: https://en.wikipedia.org/wiki/Total_order
@@ -730,13 +731,12 @@ impl<T: Clone> Clone for Reverse<T> {
730731
/// This trait can be used with `#[derive]`.
731732
///
732733
/// When `derive`d on structs, it will produce a
733-
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
734-
/// based on the top-to-bottom declaration order of the struct's members.
734+
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
735+
/// top-to-bottom declaration order of the struct's members.
735736
///
736-
/// When `derive`d on enums, variants are ordered primarily by their discriminants.
737-
/// Secondarily, they are ordered by their fields.
738-
/// By default, the discriminant is smallest for variants at the top, and
739-
/// largest for variants at the bottom. Here's an example:
737+
/// When `derive`d on enums, variants are ordered primarily by their discriminants. Secondarily,
738+
/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
739+
/// top, and largest for variants at the bottom. Here's an example:
740740
///
741741
/// ```
742742
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -748,8 +748,7 @@ impl<T: Clone> Clone for Reverse<T> {
748748
/// assert!(E::Top < E::Bottom);
749749
/// ```
750750
///
751-
/// However, manually setting the discriminants can override this default
752-
/// behavior:
751+
/// However, manually setting the discriminants can override this default behavior:
753752
///
754753
/// ```
755754
/// #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -765,51 +764,178 @@ impl<T: Clone> Clone for Reverse<T> {
765764
///
766765
/// Lexicographical comparison is an operation with the following properties:
767766
/// - Two sequences are compared element by element.
768-
/// - The first mismatching element defines which sequence is lexicographically less or greater than the other.
769-
/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than the other.
770-
/// - If two sequences have equivalent elements and are of the same length, then the sequences are lexicographically equal.
767+
/// - The first mismatching element defines which sequence is lexicographically less or greater
768+
/// than the other.
769+
/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than
770+
/// the other.
771+
/// - If two sequences have equivalent elements and are of the same length, then the sequences are
772+
/// lexicographically equal.
771773
/// - An empty sequence is lexicographically less than any non-empty sequence.
772774
/// - Two empty sequences are lexicographically equal.
773775
///
774776
/// ## How can I implement `Ord`?
775777
///
776-
/// `Ord` requires that the type also be [`PartialOrd`] and [`Eq`] (which requires [`PartialEq`]).
778+
/// `Ord` requires that the type also be [`PartialOrd`], [`PartialEq`], and [`Eq`].
777779
///
778-
/// Then you must define an implementation for [`cmp`]. You may find it useful to use
779-
/// [`cmp`] on your type's fields.
780+
/// Because `Ord` implies a stronger ordering relationship than [`PartialOrd`], and both `Ord` and
781+
/// [`PartialOrd`] must agree, you must choose how to implement `Ord` **first**. You can choose to
782+
/// derive it, or implement it manually. If you derive it, you should derive all four traits. If you
783+
/// implement it manually, you should manually implement all four traits, based on the
784+
/// implementation of `Ord`.
780785
///
781-
/// Here's an example where you want to sort people by height only, disregarding `id`
782-
/// and `name`:
786+
/// Here's an example where you want to define the `Character` comparison by `health` and
787+
/// `experience` only, disregarding the field `mana`:
783788
///
784789
/// ```
785790
/// use std::cmp::Ordering;
786791
///
787-
/// #[derive(Eq)]
788-
/// struct Person {
789-
/// id: u32,
790-
/// name: String,
791-
/// height: u32,
792+
/// struct Character {
793+
/// health: u32,
794+
/// experience: u32,
795+
/// mana: f32,
792796
/// }
793797
///
794-
/// impl Ord for Person {
795-
/// fn cmp(&self, other: &Self) -> Ordering {
796-
/// self.height.cmp(&other.height)
798+
/// impl Ord for Character {
799+
/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
800+
/// self.experience
801+
/// .cmp(&other.experience)
802+
/// .then(self.health.cmp(&other.health))
797803
/// }
798804
/// }
799805
///
800-
/// impl PartialOrd for Person {
806+
/// impl PartialOrd for Character {
801807
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
802808
/// Some(self.cmp(other))
803809
/// }
804810
/// }
805811
///
806-
/// impl PartialEq for Person {
812+
/// impl PartialEq for Character {
807813
/// fn eq(&self, other: &Self) -> bool {
808-
/// self.height == other.height
814+
/// self.health == other.health && self.experience == other.experience
815+
/// }
816+
/// }
817+
///
818+
/// impl Eq for Character {}
819+
/// ```
820+
///
821+
/// If all you need is to `slice::sort` a type by a field value, it can be simpler to use
822+
/// `slice::sort_by_key`.
823+
///
824+
/// ## Examples of incorrect `Ord` implementations
825+
///
826+
/// ```
827+
/// use std::cmp::Ordering;
828+
///
829+
/// #[derive(Debug)]
830+
/// struct Character {
831+
/// health: f32,
832+
/// }
833+
///
834+
/// impl Ord for Character {
835+
/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
836+
/// if self.health < other.health {
837+
/// Ordering::Less
838+
/// } else if self.health > other.health {
839+
/// Ordering::Greater
840+
/// } else {
841+
/// Ordering::Equal
842+
/// }
843+
/// }
844+
/// }
845+
///
846+
/// impl PartialOrd for Character {
847+
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
848+
/// Some(self.cmp(other))
849+
/// }
850+
/// }
851+
///
852+
/// impl PartialEq for Character {
853+
/// fn eq(&self, other: &Self) -> bool {
854+
/// self.health == other.health
855+
/// }
856+
/// }
857+
///
858+
/// impl Eq for Character {}
859+
///
860+
/// let a = Character { health: 4.5 };
861+
/// let b = Character { health: f32::NAN };
862+
///
863+
/// // Mistake: floating-point values do not form a total order and using the built-in comparison
864+
/// // operands to implement `Ord` irregardless of that reality does not change it. Use
865+
/// // `f32::total_cmp` if you need a total order for floating-point values.
866+
///
867+
/// // Reflexivity requirement of `Ord` is not given.
868+
/// assert!(a == a);
869+
/// assert!(b != b);
870+
///
871+
/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
872+
/// // true, not both or neither.
873+
/// assert_eq!((a < b) as u8 + (b < a) as u8, 0);
874+
/// ```
875+
///
876+
/// ```
877+
/// use std::cmp::Ordering;
878+
///
879+
/// #[derive(Debug)]
880+
/// struct Character {
881+
/// health: u32,
882+
/// experience: u32,
883+
/// }
884+
///
885+
/// impl PartialOrd for Character {
886+
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
887+
/// Some(self.cmp(other))
888+
/// }
889+
/// }
890+
///
891+
/// impl Ord for Character {
892+
/// fn cmp(&self, other: &Self) -> std::cmp::Ordering {
893+
/// if self.health < 50 {
894+
/// self.health.cmp(&other.health)
895+
/// } else {
896+
/// self.experience.cmp(&other.experience)
897+
/// }
898+
/// }
899+
/// }
900+
///
901+
/// // For performance reasons implementing `PartialEq` this way is not the idiomatic way, but it
902+
/// // ensures consistent behavior between `PartialEq`, `PartialOrd` and `Ord` in this example.
903+
/// impl PartialEq for Character {
904+
/// fn eq(&self, other: &Self) -> bool {
905+
/// self.cmp(other) == Ordering::Equal
809906
/// }
810907
/// }
908+
///
909+
/// impl Eq for Character {}
910+
///
911+
/// let a = Character {
912+
/// health: 3,
913+
/// experience: 5,
914+
/// };
915+
/// let b = Character {
916+
/// health: 10,
917+
/// experience: 77,
918+
/// };
919+
/// let c = Character {
920+
/// health: 143,
921+
/// experience: 2,
922+
/// };
923+
///
924+
/// // Mistake: The implementation of `Ord` compares different fields depending on the value of
925+
/// // `self.health`, the resulting order is not total.
926+
///
927+
/// // Transitivity requirement of `Ord` is not given. If a is smaller than b and b is smaller than
928+
/// // c, by transitive property a must also be smaller than c.
929+
/// assert!(a < b && b < c && c < a);
930+
///
931+
/// // Antisymmetry requirement of `Ord` is not given. Only one of a < c and c < a is allowed to be
932+
/// // true, not both or neither.
933+
/// assert_eq!((a < c) as u8 + (c < a) as u8, 2);
811934
/// ```
812935
///
936+
/// The documentation of [`PartialOrd`] contains further examples, for example it's wrong for
937+
/// [`PartialOrd`] and [`PartialEq`] to disagree.
938+
///
813939
/// [`cmp`]: Ord::cmp
814940
#[doc(alias = "<")]
815941
#[doc(alias = ">")]
@@ -924,8 +1050,12 @@ pub macro Ord($item:item) {
9241050

9251051
/// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order).
9261052
///
927-
/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
928-
/// the `<`, `<=`, `>`, and `>=` operators, respectively.
1053+
/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using the `<`, `<=`, `>`, and
1054+
/// `>=` operators, respectively.
1055+
///
1056+
/// This trait should **only** contain the comparison logic for a type **if one plans on only
1057+
/// implementing `PartialOrd` but not [`Ord`]**. Otherwise the comparison logic should be in [`Ord`]
1058+
/// and this trait implemented with `Some(self.cmp(other))`.
9291059
///
9301060
/// The methods of this trait must be consistent with each other and with those of [`PartialEq`].
9311061
/// The following conditions must hold:
@@ -937,26 +1067,25 @@ pub macro Ord($item:item) {
9371067
/// 5. `a >= b` if and only if `a > b || a == b`
9381068
/// 6. `a != b` if and only if `!(a == b)`.
9391069
///
940-
/// Conditions 2–5 above are ensured by the default implementation.
941-
/// Condition 6 is already ensured by [`PartialEq`].
1070+
/// Conditions 2–5 above are ensured by the default implementation. Condition 6 is already ensured
1071+
/// by [`PartialEq`].
9421072
///
9431073
/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
944-
/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
945-
/// easy to accidentally make them disagree by deriving some of the traits and manually
946-
/// implementing others.
1074+
/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's easy to
1075+
/// accidentally make them disagree by deriving some of the traits and manually implementing others.
9471076
///
948-
/// The comparison relations must satisfy the following conditions
949-
/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
1077+
/// The comparison relations must satisfy the following conditions (for all `a`, `b`, `c` of type
1078+
/// `A`, `B`, `C`):
9501079
///
951-
/// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A:
952-
/// PartialOrd<C>`, then `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
953-
/// This must also work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`,
954-
/// `C: PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
955-
/// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b > a`.
1080+
/// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A: PartialOrd<C>`, then `a
1081+
/// < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. This must also
1082+
/// work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`, `C:
1083+
/// PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
1084+
/// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b >
1085+
/// a`.
9561086
///
957-
/// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>`
958-
/// (transitive) impls are not forced to exist, but these requirements apply
959-
/// whenever they do exist.
1087+
/// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>` (transitive) impls are not forced
1088+
/// to exist, but these requirements apply whenever they do exist.
9601089
///
9611090
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
9621091
/// specified, but users of the trait must ensure that such logic errors do *not* result in
@@ -992,12 +1121,10 @@ pub macro Ord($item:item) {
9921121
///
9931122
/// ## Strict and non-strict partial orders
9941123
///
995-
/// The `<` and `>` operators behave according to a *strict* partial order.
996-
/// However, `<=` and `>=` do **not** behave according to a *non-strict*
997-
/// partial order.
998-
/// That is because mathematically, a non-strict partial order would require
999-
/// reflexivity, i.e. `a <= a` would need to be true for every `a`. This isn't
1000-
/// always the case for types that implement `PartialOrd`, for example:
1124+
/// The `<` and `>` operators behave according to a *strict* partial order. However, `<=` and `>=`
1125+
/// do **not** behave according to a *non-strict* partial order. That is because mathematically, a
1126+
/// non-strict partial order would require reflexivity, i.e. `a <= a` would need to be true for
1127+
/// every `a`. This isn't always the case for types that implement `PartialOrd`, for example:
10011128
///
10021129
/// ```
10031130
/// let a = f64::sqrt(-1.0);
@@ -1009,13 +1136,12 @@ pub macro Ord($item:item) {
10091136
/// This trait can be used with `#[derive]`.
10101137
///
10111138
/// When `derive`d on structs, it will produce a
1012-
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
1013-
/// based on the top-to-bottom declaration order of the struct's members.
1139+
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the
1140+
/// top-to-bottom declaration order of the struct's members.
10141141
///
1015-
/// When `derive`d on enums, variants are primarily ordered by their discriminants.
1016-
/// Secondarily, they are ordered by their fields.
1017-
/// By default, the discriminant is smallest for variants at the top, and
1018-
/// largest for variants at the bottom. Here's an example:
1142+
/// When `derive`d on enums, variants are primarily ordered by their discriminants. Secondarily,
1143+
/// they are ordered by their fields. By default, the discriminant is smallest for variants at the
1144+
/// top, and largest for variants at the bottom. Here's an example:
10191145
///
10201146
/// ```
10211147
/// #[derive(PartialEq, PartialOrd)]
@@ -1027,8 +1153,7 @@ pub macro Ord($item:item) {
10271153
/// assert!(E::Top < E::Bottom);
10281154
/// ```
10291155
///
1030-
/// However, manually setting the discriminants can override this default
1031-
/// behavior:
1156+
/// However, manually setting the discriminants can override this default behavior:
10321157
///
10331158
/// ```
10341159
/// #[derive(PartialEq, PartialOrd)]
@@ -1046,8 +1171,8 @@ pub macro Ord($item:item) {
10461171
/// generated from default implementations.
10471172
///
10481173
/// However it remains possible to implement the others separately for types which do not have a
1049-
/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 ==
1050-
/// false` (cf. IEEE 754-2008 section 5.11).
1174+
/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == false`
1175+
/// (cf. IEEE 754-2008 section 5.11).
10511176
///
10521177
/// `PartialOrd` requires your type to be [`PartialEq`].
10531178
///
@@ -1056,7 +1181,6 @@ pub macro Ord($item:item) {
10561181
/// ```
10571182
/// use std::cmp::Ordering;
10581183
///
1059-
/// #[derive(Eq)]
10601184
/// struct Person {
10611185
/// id: u32,
10621186
/// name: String,
@@ -1080,11 +1204,13 @@ pub macro Ord($item:item) {
10801204
/// self.height == other.height
10811205
/// }
10821206
/// }
1207+
///
1208+
/// impl Eq for Person {}
10831209
/// ```
10841210
///
1085-
/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here
1086-
/// is an example of `Person` types who have a floating-point `height` field that
1087-
/// is the only field to be used for sorting:
1211+
/// You may also find it useful to use [`partial_cmp`] on your type's fields. Here is an example of
1212+
/// `Person` types who have a floating-point `height` field that is the only field to be used for
1213+
/// sorting:
10881214
///
10891215
/// ```
10901216
/// use std::cmp::Ordering;
@@ -1108,6 +1234,38 @@ pub macro Ord($item:item) {
11081234
/// }
11091235
/// ```
11101236
///
1237+
/// ## Examples of incorrect `PartialOrd` implementations
1238+
///
1239+
/// ```
1240+
/// use std::cmp::Ordering;
1241+
///
1242+
/// #[derive(PartialEq, Debug)]
1243+
/// struct Character {
1244+
/// health: u32,
1245+
/// experience: u32,
1246+
/// }
1247+
///
1248+
/// impl PartialOrd for Character {
1249+
/// fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1250+
/// Some(self.health.cmp(&other.health))
1251+
/// }
1252+
/// }
1253+
///
1254+
/// let a = Character {
1255+
/// health: 10,
1256+
/// experience: 5,
1257+
/// };
1258+
/// let b = Character {
1259+
/// health: 10,
1260+
/// experience: 77,
1261+
/// };
1262+
///
1263+
/// // Mistake: `PartialEq` and `PartialOrd` disagree with each other.
1264+
///
1265+
/// assert_eq!(a.partial_cmp(&b).unwrap(), Ordering::Equal); // a == b according to `PartialOrd`.
1266+
/// assert_ne!(a, b); // a != b according to `PartialEq`.
1267+
/// ```
1268+
///
11111269
/// # Examples
11121270
///
11131271
/// ```

0 commit comments

Comments
 (0)
Please sign in to comment.