-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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_cmp
compares 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
,gt
andge
continues 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.