Open andrewrk opened 8 years ago
Also, if you do ?void
or equivalent, then you have effectively constructed a boolean, and this can codegen to the same as what a boolean codegens to.
Based on @LemonBoy 's suggestion copying the relevant parts of #5162 to here. Though it seems you called this proposal out already above.
Edited the parts below to be more concise.
Optional struct
s can have some drastic effects on the sizes. Specifically if the alignment of a field is large (e.g. larger than the normal sizes of each field) an optional struct can easily double in size e.g.:
const S = struct {
a: u8 align(64),
};
test "Alignment" {
std.debug.assert(@sizeOf(S) == 64);
std.debug.assert(@sizeOf(?S) == 128);
std.debug.assert(@sizeOf(?S) == @sizeOf(S) + @alignOf(S));
}
Since Zig doesn't have a stable ABI for its own structs it should be possible to optimize an optional type's layout and size to use the generated padding to host the extra optional field.
This would effectively bring the @sizeOf(?S) in the example down to 64 and shouldn't have any issues with e.g. var set_of_s: [100]S = undefined; as the type S would stay properly aligned.
Of course it won't always be possible to do this optimization, in which case the optional type would have to add the additional field as normal.
Also to highlight since it's relevant to this issue - @SpexGuy 's suggestion of Explicit Sentinel Optionals from: https://github.com/ziglang/zig/issues/3806#issuecomment-588500376
This is accepted which means that:
?T
is a non-memory-defined layout, with the exception of pointers, which have well-defined memory layout?T
where T
has no well-defined memory layout, zig is allowed to choose any representation for the ?T
&foo.?
is legal; you can take the pointer of T
in an ?T
. The T has to be addressable.?T
. The optional bit is not addressable.
Track which values are used when data sizes are bigger than necessary and use those states for maybe types. For example,
?bool
could use value2
of the bool as the null value, and??bool
can use value3
for the null value, and so on.If we have spaces in structs for alignment purposes, that space could be used for the null value, or if any of the fields have null space available, such as a struct with a bool field in it somewhere.