-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Ensure derive(PartialOrd) is no longer accidentally exponential #50011
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bors r+
@bors r+ |
📌 Commit 3ecaeba has been approved by |
Argh, messed up the default there, sorry. |
@bors r+ Please test this on various combinations of greater than/less than just in case 😄 |
📌 Commit d0e6f70 has been approved by |
Your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem. Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
// `self.fi.partial_cmp(other.fi)` | ||
let cmp = cx.expr_method_call(span, | ||
cx.expr_addr_of(span, self_f), | ||
Ident::from_str("partial_cmp"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this avoid using an inherent partial_cmp
method if the underlying type doesn't actually implement PartialOrd
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be PartialOrd::partial_cmp(...)
- like Clone::clone
deriving (IIRC).
|
||
let default = ordering_path(cx, "Equal"); | ||
// `_.unwrap_or(Ordering::Equal)` | ||
cx.expr_method_call(span, cmp, Ident::from_str("unwrap_or"), vec![default]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not sure about what happens if there is a trait implemented by Option<Ordering>
in scope with an unwrap_or
method.
@Manishearth did you mean to r+, if this needs additional tests? Additionally for nox’s concern (which I think suggest to use UFCS, like other derives seem to do), and for tests failing on Travis, let’s remove this from the queue for now: @bors r- |
✌️ @nox can now approve this pull request |
1 similar comment
✌️ @nox can now approve this pull request |
I think there's actually a good range of tests for this already — that's why the previous commits were caught. I just... might not... have been running all the tests before pushing... 😳 I think everything's passing now, but let's wait for Travis to confirm. |
(Travis passed) |
Ping from triage @nox! You are now delegated to review this PR! |
// ) | ||
// self.f1.partial_cmp(other.f1).unwrap_or(Ordering::Equal) | ||
// .then_with(|| self.f2.partial_cmp(other.f2).unwrap_or(Ordering::Equal)) | ||
// != Ordering::Greater |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO those should just emit nested match
expressions that return false
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be any direct advantage to doing so? The main reason I used functions was because of the existing issues with match
codegen efficiency, but I don't see that it makes a huge difference either way.
|
||
let strict_ineq = cx.expr_binary(span, strict_op, self_f.clone(), other_f.clone()); | ||
// `self.fi.partial_cmp(other.fi).unwrap_or(Ordering::Equal)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment seems outdated, given we now use UFCS.
|
||
let and = cx.expr_binary(span, BinOpKind::And, deleg_cmp, subexpr); | ||
cx.expr_binary(span, BinOpKind::Or, strict_ineq, and) | ||
// `self.fi.partial_cmp(other.fi).unwrap_or(Ordering::Equal).then_with(...)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment seems outdated, given we now use UFCS.
211ca31
to
228228c
Compare
☔ The latest upstream changes (presumably #49986) made this pull request unmergeable. Please resolve the merge conflicts. |
Previously, two comparison operations would be generated for each field, each of which could delegate to another derived PartialOrd. Now we use ordering and optional chaining to ensure each pair of fields is only compared once.
228228c
to
6805e5a
Compare
Ping from triage, @nox! Looks like this is ready to review again. |
Nit: AFAIK it's not called UFCS anymore, but Fully-Qualified Syntax |
I still don't like that this is not using proper match expressions. I'll defer to @Manishearth for the final review (not sure why he delegated me to review it anyway). |
Ping from triage @Manishearth! This PR needs your review. |
I don't have time to review this rn, sorry. |
oh, the logic has already been reviewed for this code looks good. @bors r+ |
📌 Commit 6805e5a has been approved by |
@bors p=0 |
Ensure derive(PartialOrd) is no longer accidentally exponential Previously, two comparison operations would be generated for each field, each of which could delegate to another derived PartialOrd. Now we use ordering and optional chaining to ensure each pair of fields is only compared once, addressing #49650 (comment). Closes #49505. r? @Manishearth (sorry for changing it again so soon!) Close #50755
☀️ Test successful - status-appveyor, status-travis |
Previously, two comparison operations would be generated for each field, each of which could delegate to another derived PartialOrd. Now we use ordering and optional chaining to ensure each pair of fields is only compared once, addressing #49650 (comment).
Closes #49505.
r? @Manishearth (sorry for changing it again so soon!)
Close #50755