-
Notifications
You must be signed in to change notification settings - Fork 743
Implement Default
trait
#480
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
This definitely needs a rebase. |
I'm not too fond on this, what's the advantage vs. using |
I guess you can do something like:
But that seems like it can turn into a footgun to me. |
|
If we have |
That's a good point, but I'm not sure implementing Anyway, will do a first review pass, I don't want my opinion to prevent adding this to bindgen if other people consider it's useful. @fitzgen, any opinion here? |
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.
A few nits here and there, otherwise looks ok. Please add a test for the config.
One question, what about if instead of tracking what types can and can't derive default, we simply add a convenience method to each struct/union?
I sincerely don't see the advantage of tracking all these fields if the result it's going to be a zeroed struct.
It makes sense when deriving copy because we don't want to implement it always (we don't do so when a type has a destructor, etc.). Similarly, it makes sense when deriving Debug because we can't write Debug
manually, but I don't see the point in tracking whether Default
is derivable if the result is just mem::zeroed()
.
Note that this will be UB if there's a rust-like enum inside the struct (it could have an invalid discriminant), as far as I know.
That's something you can't do with safe rust even when all fields are public, @nox.
src/codegen/mod.rs
Outdated
@@ -689,6 +689,7 @@ impl<'a> CodeGenerator for Vtable<'a> { | |||
.item() | |||
.pub_() | |||
.with_attr(attributes::repr("C")) | |||
.with_attr(attributes::derives(&["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.
Please do this only if ctx.options().derive_default
.
src/codegen/mod.rs
Outdated
if item.can_derive_default(ctx, ()) { | ||
derives.push("Default"); | ||
} else { | ||
needs_default_impl = true; |
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 needs to be needs_default_impl = ctx.options().derive_default
. Please add a test for this (see tests/headers/no-derive-debug.h
for a similar example).
src/ir/comp.rs
Outdated
@@ -891,6 +904,53 @@ impl CanDeriveDebug for CompInfo { | |||
can_derive_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.
nit: newline missing.
src/ir/comp.rs
Outdated
ctx: &BindgenContext, | ||
layout: Option<Layout>) | ||
-> bool { | ||
{ |
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.
nit: Why this block wrapping the full function? We should be able to just remove these braces and deindent it, right?
@@ -10,3 +10,6 @@ pub struct std_allocator_traits<_Alloc> { | |||
pub _address: u8, | |||
pub _phantom_0: ::std::marker::PhantomData<_Alloc>, | |||
} | |||
impl <_Alloc> Default for std_allocator_traits<_Alloc> { |
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.
Probably we shouldn't derive default for incomplete/unsized types, but i understand it's needed because of derive bounds with template parameters, right?
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.
Yes, it's hard to trace which type could be used in where, such as base_members
, template_args
, fields
or ref_template
. So, the most straight way is to implement Default
as much as possible.
We have introduced a lot of auto generated fields to reconstruct C/C++/ObjC ABI, from a end user viewpoint, those public magic fields are more difficulty understanding than To use property could be a alternative, but Rust lack of Abstract and Concrete Fields in Traits like On the other hand, I don't think we must trace all fields who implement Anyway, I think we could support the |
Sure, I agree, over all if the fields (like the padding fields) depend on a per-platform basis. The padding fields will probably go away eventually once Rust supports custom alignment, and I think the others aren't that problematic IMO.
Sure, my point is that I think we shouldn't bother trying to derive when possible, because that's most of the code this PR adds, and it's completely unneeded. You could argue for the readability of the bindings, but I don't think we should care a lot about it when it involves complexity in the code.
Making it opt-in looks good to me, I think it's better. |
Yes, the best solution is upstream Rust implement all of those dirty works in the language like
I think the most different between those two strategies is how we reconstruct the C/C++/ObjC ABI. If we only use those plain data, such as build-in primitive types or array, I agree the But, if we want to use those Till now, we only use some
|
I'd argue for keeping the complexity away for as long as we don't need it. A comment pointing that if more complex |
I don't have too many strong opinions here, but here are two thoughts: Maintaining bindgen is fairly difficult, so it is important to minimize complexity by choosing to support only one of (a) default impls, and (b) the pub fields with mem::zeroed initialization. It seems to me like in the long term the default impls is a more correct approach, but we do need to make sure it is robust (I haven't looked at any patches here). |
Ok, let's do that then, @flier feel free to address comments and squash commits, and we'll merge this afterwards. |
Glad to see it 👍 |
@flier This still hasn't been rebased against current master. The merge commits in your branch has to be dropped. |
@flier Perhaps this guide can help you: https://github.com/servo/servo/wiki/Beginner's-guide-to-rebasing-and-squashing |
Thanks @KiChjang, seems ok :) |
src/lib.rs
Outdated
@@ -581,6 +591,7 @@ impl Default for BindgenOptions { | |||
emit_ast: false, | |||
emit_ir: false, | |||
derive_debug: true, | |||
derive_default: true, |
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 make it opt-in instead as discussed? Hmm, though that means that the option should be derive-default
. I'm happy turning it on for testing so it gets more coverage (see the call to no_unstable_rust
in test/test.rs
).
Perhaps we should start doing something like --derive-default={yes,no}
? Not sure how easy would that be.
What do you think?
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 have added a new option with-derive-default
and disable it by default, when we use it on tests, just enable the hidden no-derive-default
option which has higher priority.
let prepend = ["bindgen",
"--with-derive-default",
header_str,
"--raw-line",
"",
"--raw-line",
"#![allow(non_snake_case)]",
"--raw-line",
""];
let args = prepend.into_iter()
.map(ToString::to_string)
.chain(flags.into_iter());
builder_from_flags(args)
.map(|(builder, _)| Some(builder.no_unstable_rust()))
@bors-servo r+ |
📌 Commit 5446818 has been approved by |
Implement `Default` trait We need `Default` trait to handle so many auto generated fields when create new structure.
💔 Test failed - status-travis |
You need to rebase to include the newest test changes, should be straight forward :) |
@bors-servo r+ Can't wait for this to bitrot all the other PRs ;) Thanks @flier! |
📌 Commit 25b68ba has been approved by |
Implement `Default` trait We need `Default` trait to handle so many auto generated fields when create new structure.
☀️ Test successful - status-travis |
We need
Default
trait to handle so many auto generated fields when create new structure.