Fix derived PartialOrd operators #81384
Conversation
|
r? @davidtwco (rust-highfive has picked a reviewer for you, use r? to override) |
|
As noted in in Zulip this will require a crater run. |
|
@bors try @rust-timer queue |
|
Awaiting bors try build completion. |
|
⌛ Trying commit 5b3d70eaefc1e4375f955a5a94e235e60570489b with merge 69fff217252aad8de0c3b890699c7c4275062d97... |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
It will have to wait for a try build and crater run, but should be otherwise ready for review. |
|
Looks like fix for earlier build issue landed in #81380. @bors try @rust-timer queue |
|
Awaiting bors try build completion. |
|
⌛ Trying commit 96f4c7906a5f30d39eae896b974f4b86f8b90506 with merge 9d00041aa7f1137de819a10d3cbf8e8e48105d70... |
This comment has been minimized.
This comment has been minimized.
|
☀️ Try build successful - checks-actions |
|
Queued 9d00041aa7f1137de819a10d3cbf8e8e48105d70 with parent 84864bf, future comparison URL. @rustbot label: +S-waiting-on-perf |
|
Finished benchmarking try commit (9d00041aa7f1137de819a10d3cbf8e8e48105d70): comparison url. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up. @bors rollup=never |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
|
Some coverage tests need to be updated. |
|
Updated the test output. I will open an issue about producing a canonical implementation. @rustbot label: +S-waiting-on-review -S-waiting-on-author |
|
@bors r+ |
|
📌 Commit 62366ee has been approved by |
|
☀️ Test successful - checks-actions |
|
|
…dtolnay Use `partial_cmp` to implement tuple `lt`/`le`/`ge`/`gt` In today's implementation, `(A, B)::gt` contains calls to *both* `A::eq` *and* `A::gt`. That's fine for primitives, but for things like `String`s it's kinda weird -- `(String, usize)::gt` has a call to both `bcmp` and `memcmp` (<https://rust.godbolt.org/z/7jbbPMesf>) because when `bcmp` says the `String`s aren't equal, it turns around and calls `memcmp` to find out which one's bigger. This PR changes the implementation to instead implement `(A, …, C, Z)::gt` using `A::partial_cmp`, `…::partial_cmp`, `C::partial_cmp`, and `Z::gt`. (And analogously for `lt`, `le`, and `ge`.) That way expensive comparisons don't need to be repeated. Technically this is an observable change on stable, so I've marked it `needs-fcp` + `T-libs-api` and will r? rust-lang/libs-api I'm hoping that this will be non-controversial, however, since it's very similar to the observable changes that were made to the derives (rust-lang#81384 rust-lang#98655) -- like those, this only changes behaviour if a type overrode behaviour in a way inconsistent with the rules for the various traits involved. (The first commit here is rust-lang#108156, adding the codegen test, which I used to make sure this doesn't regress behaviour for primitives.) Zulip conversation about this change: <https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/.60.3E.60.20on.20Tuples/near/328392927>.
The derived implementation of
partial_cmpcompares matching fields oneby 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,gtandgecontinues the computation when the result of a field comparison isNone, consequently those operators are not transitive and inconsistentwith
partial_cmp.Fix the inconsistency by using the default implementation that fall-backs
to the
partial_cmp. This also avoids creating very deeply nestedclosures that were quite costly to compile.
Fixes #81373.
Helps with #81278, #80118.