@@ -61,11 +61,13 @@ use self::Ordering::*;
61
61
/// The equality relation `==` must satisfy the following conditions
62
62
/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
63
63
///
64
- /// - **Symmetric **: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
64
+ /// - **Symmetry **: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
65
65
/// implies `b == a`**; and
66
66
///
67
- /// - **Transitive **: if `A: PartialEq<B>` and `B: PartialEq<C>` and `A:
67
+ /// - **Transitivity **: if `A: PartialEq<B>` and `B: PartialEq<C>` and `A:
68
68
/// PartialEq<C>`, then **`a == b` and `b == c` implies `a == c`**.
69
+ /// This must also work for longer chains, such as when `A: PartialEq<B>`, `B: PartialEq<C>`,
70
+ /// `C: PartialEq<D>`, and `A: PartialEq<D>` all exist.
69
71
///
70
72
/// Note that the `B: PartialEq<A>` (symmetric) and `A: PartialEq<C>`
71
73
/// (transitive) impls are not forced to exist, but these requirements apply
@@ -76,6 +78,25 @@ use self::Ordering::*;
76
78
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
77
79
/// methods.
78
80
///
81
+ /// ## Cross-crate considerations
82
+ ///
83
+ /// Upholding the requirements stated above can become tricky when one crate implements `PartialEq`
84
+ /// for a type of another crate (i.e., to allow comparing one of its own types with a type from the
85
+ /// standard library). The recommendation is to never implement this trait for a foreign type. In
86
+ /// other words, such a crate should do `impl PartialEq<ForeignType> for LocalType`, but it should
87
+ /// *not* do `impl PartialEq<LocalType> for ForeignType`.
88
+ ///
89
+ /// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local
90
+ /// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T == U`. In
91
+ /// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ...
92
+ /// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the
93
+ /// crate defining `T` already knows about. This rules out transitive chains where downstream crates
94
+ /// can add new `impl`s that "stitch together" comparisons of foreign types in ways that violate
95
+ /// transitivity.
96
+ ///
97
+ /// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding
98
+ /// more `PartialEq` implementations can cause build failures in downstream crates.
99
+ ///
79
100
/// ## Derivable
80
101
///
81
102
/// This trait can be used with `#[derive]`. When `derive`d on structs, two
@@ -920,20 +941,43 @@ pub macro Ord($item:item) {
920
941
/// easy to accidentally make them disagree by deriving some of the traits and manually
921
942
/// implementing others.
922
943
///
923
- /// The comparison must satisfy, for all `a`, `b` and `c`:
944
+ /// The comparison relations must satisfy the following conditions
945
+ /// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
924
946
///
925
- /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
926
- /// - duality: `a < b` if and only if `b > a`.
947
+ /// - **Transitivity**: if `A: PartialOrd<B>` and `B: PartialOrd<C>` and `A:
948
+ /// PartialOrd<C>`, then `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
949
+ /// This must also work for longer chains, such as when `A: PartialOrd<B>`, `B: PartialOrd<C>`,
950
+ /// `C: PartialOrd<D>`, and `A: PartialOrd<D>` all exist.
951
+ /// - **Duality**: if `A: PartialOrd<B>` and `B: PartialOrd<A>`, then `a < b` if and only if `b > a`.
927
952
///
928
- /// Note that these requirements mean that the trait itself must be implemented symmetrically and
929
- /// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
930
- /// PartialOrd<V>` .
953
+ /// Note that the `B: PartialOrd<A>` (dual) and `A: PartialOrd<C>`
954
+ /// (transitive) impls are not forced to exist, but these requirements apply
955
+ /// whenever they do exist .
931
956
///
932
957
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
933
958
/// specified, but users of the trait must ensure that such logic errors do *not* result in
934
959
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
935
960
/// methods.
936
961
///
962
+ /// ## Cross-crate considerations
963
+ ///
964
+ /// Upholding the requirements stated above can become tricky when one crate implements `PartialOrd`
965
+ /// for a type of another crate (i.e., to allow comparing one of its own types with a type from the
966
+ /// standard library). The recommendation is to never implement this trait for a foreign type. In
967
+ /// other words, such a crate should do `impl PartialOrd<ForeignType> for LocalType`, but it should
968
+ /// *not* do `impl PartialOrd<LocalType> for ForeignType`.
969
+ ///
970
+ /// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local
971
+ /// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T < U`. In
972
+ /// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ...
973
+ /// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate
974
+ /// defining `T` already knows about. This rules out transitive chains where downstream crates can
975
+ /// add new `impl`s that "stitch together" comparisons of foreign types in ways that violate
976
+ /// transitivity.
977
+ ///
978
+ /// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding
979
+ /// more `PartialOrd` implementations can cause build failures in downstream crates.
980
+ ///
937
981
/// ## Corollaries
938
982
///
939
983
/// The following corollaries follow from the above requirements:
0 commit comments