I recently needed to initialize a bindgen-generated struct with lots of fields. It doesn’t derive Default because it’s unnecessary for most structs in FFI layer, but I found that
let data = Data {
a: 10,
..Default::default()
}
Requires Data to impl Default. I would expect this only to be the case for Data::default() but with partial initialization why does rustc put this requirement on the struct? Shouldn’t it just check if the actual fields implement Default and not the whole struct? Is there a reason for that? It would be handy to have this working.
..{expression} in this context doesn't look at individual fields. Instead, the expression can be anything that's the same type as the containing struct -- in this case Data. So you could do this for example:
fn replace_a(other_data: Data) -> Data {
Data {
a: 10,
..other_data
}
}
So Default::default() in your OP needs to produce a Data. It isData::default(). (And there is no implementation of Default for "some partial set of an arbitrary struct" that Default::default() could otherwise resolve to.)
Default::default() desugars to <_ as Default>::default(), which inference figures out is <Data as Default>::default().
That's just a normal expression position -- you can do ..foo() or whatever there too. There's nothing special about Default::default() as the expression passed to FRU.
I do hope Rust will get a new feature to help with this case, though. Preferably the one that was discussed here:
I see. This syntax is a little ambiguous to read. I can now read it both ways and they both make sense, so not sure which one sounds more precise: “Use default values for the fields from the Default impl of the struct” OR “ Use the default values for the fields independent of the struct’s Default impl” .
This is the one that's correct. Notably, the default for the b field in Data might be 12345, even though it's an i32 (which has <i32 as Default>::default() == 0).
If it helps,
let data = Data {
a: 10,
..Default::default()
};
Is the same as
let data_defaults: Data = Default::default();
let data = Data {
a: 10,
..data_defaults
};