diff options
| author | Ralf Jung <post@ralfj.de> | 2023-12-26 19:52:20 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2023-12-26 20:02:39 +0100 |
| commit | baaf6d706ac3cb8b306ebede165706b7a0038415 (patch) | |
| tree | e2fad16ec3f6bc89a82fa6f41b9a125f15832e96 /library/core | |
| parent | 3e389ef6d50c2cae6b561a04adb9224e666eb964 (diff) | |
| download | rust-baaf6d706ac3cb8b306ebede165706b7a0038415.tar.gz rust-baaf6d706ac3cb8b306ebede165706b7a0038415.zip | |
explain what crates should do when adding comparison with foreign types
Diffstat (limited to 'library/core')
| -rw-r--r-- | library/core/src/cmp.rs | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index e95410ba648..9c18d5573e6 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -78,6 +78,25 @@ use self::Ordering::*; /// 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 assue 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 @@ -939,6 +958,25 @@ pub macro Ord($item:item) { /// 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 assue 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: |
