-
Notifications
You must be signed in to change notification settings - Fork 707
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
Derive partialeq "manually" when possible #1012
Derive partialeq "manually" when possible #1012
Conversation
src/codegen/impl_partialeq.rs
Outdated
}); | ||
} else { | ||
for (i, base) in comp_info.base_members().iter().enumerate() { | ||
// TODO: Move base field name generation into either in IR or in context. |
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.
@fitzgen There is a similar thing as with anonymous field names.
It's kinda works but ugly. What is the best possible way there?
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.
Let's add a field_name
member to Base
, compute it upon construction of the Base
, and then use that name both here and in codegen.
In fact, that could even be its own little PR, and we could land it independently of the rest of this stuff.
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.
In fact, that could even be its own little PR, and we could land it independently of the rest of this stuff.
Done #1014 !
src/lib.rs
Outdated
@@ -247,10 +255,6 @@ impl Builder { | |||
output_vector.push("--no-derive-debug".into()); | |||
} | |||
|
|||
if !self.options.impl_debug { |
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 suppose this was a bug...
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 should be if self.options.impl_debug { ... }
; we still want to add it to the output when set. Care to do this in a new PR?
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.
Err, I see you did that in another place. Want to submit that as a new PR or at least make it its own standalone commit?
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.
Yeah, I thought I would rebase & squash, but now I see that this PR is becoming too big.
// only for arrays greater than 32. | ||
// TODO: But is there can be only arrays? | ||
// Why inside of the can_trivially_derive_partialeq_or_partialord is map_or(false) ? | ||
return self.insert(id, Reason::ArrayTooLarge); |
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.
l.opaque().can_trivially_derive_partialeq_or_partialord()
contains a check if the array is large enough or not.
but it feels ugly, because it depends on the implementation of l.opaque().can_trivially_derive_partialeq_or_partialord()
. Do you see a better way there?
As an aside:
Now, I realize that it is generally ok to derive PartialEq
for the opaque, but what it means to derive PartialOrd
for the opaque? Maybe we should split those...
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.
We could define enum CanDerive { Yes, No(Reason) }
and have CanTriviallyDerive...
return No(ArrayTooLarge)
so that we aren't relying on implicit information here.
Now, I realize that it is generally ok to derive PartialEq for the opaque, but what it means to derive PartialOrd for the opaque? Maybe we should split those...
Want to file a new issue to discuss this?
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.
Want to file a new issue to discuss this?
Done #1013 !
@@ -143,8 +146,9 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { | |||
trace!(" we can trivially derive PartialEq or PartialOrd for the layout"); | |||
ConstrainResult::Same | |||
} else { | |||
// TODO: opaque can depend on arrays size at the moment |
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.
src/codegen/impl_partialeq.rs
Outdated
let name = match fd.name() { | ||
Some(name) => name, | ||
None => { | ||
// TODO: Bitfield stuff |
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.
@fitzgen Is it OK to just warn and don't generate PartialEq until we rule out the situation around anonymous field names?
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.
Yeah that's fine.
Generate base names upon construction As per #1012 (comment) r? @fitzgen
☔ The latest upstream changes (presumably #1016) made this pull request unmergeable. Please resolve the merge conflicts. |
6f7622e
to
86d00aa
Compare
Hm, not sure what is going on. These tests (
Seems like this struct doesn't derive |
I managed to reproduce this on my machine. This happens only on stable rustc 1.20 and not on beta/nightly because of |
☔ The latest upstream changes (presumably #1005) made this pull request unmergeable. Please resolve the merge conflicts. |
a095153
to
4932c6f
Compare
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.
Looks great! Just a couple nitpicks below.
Thanks @pepyakin !
src/codegen/impl_partialeq.rs
Outdated
} else if comp_info.kind() == CompKind::Union { | ||
tokens.push(quote! { | ||
&self.bindgen_union_field[..] == &other.bindgen_union_field[..] | ||
}); |
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 will only work if we aren't emitting Rust union
s, so it should check ctx.options().rust_features().untagged_union()
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 guess we would have CannotDeriveReason::Other
here for Rust union
s so this logic is actually OK as-is. That's pretty subtle, so we should definitely assert!(!ctx.options().rust_features().untagged_union())
in this branch.
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.
Makes sense!
quote_equals(name_ident) | ||
} else { | ||
quote! { | ||
&self. #name_ident [..] == &other. #name_ident [..] |
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.
Nice, we don't even need a loop ;)
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 was inspired by rustc itself (Just looked how it handles cases below 32 😄 )
Some(CannotDeriveReason::Other) => 2, | ||
} | ||
} | ||
rank(from) <= rank(to) |
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.
It seems like this whole rank
thing could be an implementation of PartialOrd
for CannotDeriveReason
and then we could do from <= to
. Am I missing anything?
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 took that way because I didn't want to make public the fact that they are can be ordered.
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.
And by they
I mean Option<CannotDeriveReason>
:)
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.
What do you think, @fitzgen , is it makes sense?
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.
Sure, sounds good to me
trace!("constrain: {:?}", id); | ||
|
||
if Some(CannotDeriveReason::Other) | ||
== self.cannot_derive_partialeq_or_partialord.get(&id).cloned() |
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.
Use an if-let here?
if let Some(CannotDeriveReason::Other) = ...
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.
Yep
} | ||
} | ||
|
||
fn constrain_join(&mut self, item: &Item) -> Option<CannotDeriveReason> { |
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.
Thanks for adding this!
// bindgen-flags: --with-derive-partialeq --impl-partialeq | ||
|
||
// Deriving PartialEq for rust unions is not supported. | ||
union ShouldNotDerivePartialEq { |
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.
If we make this comment use ///
or /** ... */
style, then it will appear in the expectations too, which is sometimes useful for checking that the trait you expect to derive or not is as expected.
// bindgen-flags: --rust-target 1.0 --with-derive-partialeq --impl-partialeq | ||
|
||
// This should manually derive PartialEq. | ||
union ShouldDerivePartialEq { |
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.
Ditto
4932c6f
to
b7bd43a
Compare
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.
👍 thanks!
@bors-servo r+ |
📌 Commit b7bd43a has been approved by |
💔 Test failed - status-travis |
☔ The latest upstream changes (presumably #1050) made this pull request unmergeable. Please resolve the merge conflicts. |
☀️ Test successful - status-travis |
👀 Test was successful, but fast-forwarding failed: 422 Update is not a fast forward |
Remove derive-partialeq-template-inst test. Add comments. Don't implement PartialEq for incomplete arrays Handle opaque bases and template instantiations Extract constrain_type. Extract `is whitelisted?` check Add failing partialeq-anonfield join for comps Fix: return insert if not whitelisted Delegate TypeRefs and alias to constrain_join. Delegate Template instantiations to constrain_join Add derive-partialeq-pointer.hpp test Update comment. Fix layout alignment larger that array limit Add missing test for derive-partialeq-anonfield.rs Clean Clean Fix typo in opaque-template-inst-member test Remove redudant stmt Add comment on can_supersede. Format impl_partialeq and leave a comment Extract requires_storage into it's own function. Clean
b7bd43a
to
617c55b
Compare
I rebased the PR @fitzgen ! |
@bors-servo r+ |
📌 Commit 617c55b has been approved by |
☀️ Test successful - status-travis |
Fixes #879
r? @fitzgen