diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-01-25 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2021-02-09 08:15:37 +0100 |
| commit | e4efccd4a6eef45e9648452360accab48b28f674 (patch) | |
| tree | 6ea614450c1e1fff32e46b9ad9e37f2b09117f5a /src | |
| parent | 921ec4b3fca17cc777766c240038d7d50ba98e0d (diff) | |
Fix derived PartialOrd operators
The derived implementation of `partial_cmp` compares matching fields one by one, stopping the computation when the result of a comparison is not equal to `Some(Equal)`. On the other hand the derived implementation for `lt`, `le`, `gt` and `ge` continues the computation when the result of a field comparison is `None`, consequently those operators are not transitive and inconsistent with `partial_cmp`. Fix the inconsistency by using the default implementation that fall-backs to the `partial_cmp`. This also avoids creating very deeply nested closures that were quite costly to compile.
Diffstat (limited to 'src')
| -rw-r--r-- | src/test/ui/derives/derive-partial-ord.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/src/test/ui/derives/derive-partial-ord.rs b/src/test/ui/derives/derive-partial-ord.rs new file mode 100644 index 00000000000..9078a7ffa4f --- /dev/null +++ b/src/test/ui/derives/derive-partial-ord.rs @@ -0,0 +1,60 @@ +// Checks that in a derived implementation of PartialOrd the lt, le, ge, gt methods are consistent +// with partial_cmp. Also verifies that implementation is consistent with that for tuples. +// +// run-pass + +#[derive(PartialEq, PartialOrd)] +struct P(f64, f64); + +fn main() { + let values: &[f64] = &[1.0, 2.0, f64::NAN]; + for a in values { + for b in values { + for c in values { + for d in values { + // Check impl for a tuple. + check(&(*a, *b), &(*c, *d)); + + // Check derived impl. + check(&P(*a, *b), &P(*c, *d)); + + // Check that impls agree with each other. + assert_eq!( + PartialOrd::partial_cmp(&(*a, *b), &(*c, *d)), + PartialOrd::partial_cmp(&P(*a, *b), &P(*c, *d)), + ); + } + } + } + } +} + +fn check<T: PartialOrd>(a: &T, b: &T) { + use std::cmp::Ordering::*; + match PartialOrd::partial_cmp(a, b) { + None => { + assert!(!(a < b)); + assert!(!(a <= b)); + assert!(!(a > b)); + assert!(!(a >= b)); + } + Some(Equal) => { + assert!(!(a < b)); + assert!(a <= b); + assert!(!(a > b)); + assert!(a >= b); + } + Some(Less) => { + assert!(a < b); + assert!(a <= b); + assert!(!(a > b)); + assert!(!(a >= b)); + } + Some(Greater) => { + assert!(!(a < b)); + assert!(!(a <= b)); + assert!(a > b); + assert!(a >= b); + } + } +} |
