Skip to content

make backing type of packed struct and packed union mandatory #24715

@mlugg

Description

@mlugg

Preamble

After some internal discussion, this proposal has been extracted from the accepted #19754, which previously included the part of this proposal pertaining to packed unions. Unlike #19754, this proposal is not yet accepted, and is a more contentious change. Personally, I'm not actually sure whether I think this is a good idea -- the more I think about it, the more I lean towards "no" -- but this issue is opened for discussion and consideration.

Background

When defining packed structs and (after #19754 is implemented) packed unions, you can provide a "backing integer type": a fixed-width integer type which the type has identical layout and ABI representation to. For a packed struct, the compiler checks that the total size of the fields matches the size of the specified backing integer type. For a packed union, the compiler checks that the size of every field matches the size of the specified backing integer type.

If the backing integer type is not specified, the Zig compiler infers it based on the sizes of the fields. Under the accepted #24714, those types are not allowed in extern contexts, because their ABI representation (in particular, their function parameter calling convention) is quite implicit, which is not safe.

An argument could be made that these types not being extern compatible is one particular case of a more general problem: packed aggregates exist to lay out bits in a well-defined way, and yet we are determining a crucial part of the representation implicitly, in a way which can cause footguns like ABI differences. That gives rise to this proposal:

Proposal

Always require an explicit backing integer type to be specified for packed structs and packed unions. packed struct { ... } and packed union { ... } become syntax errors; you must write packed struct(T) { ... } and packed union(T) { ... } respectively. Likewise, require the backing_integer to be non-null when reifying such types with @Type .

Notably, this proposal would effectively supersede most of #24714, because packed structs/unions could not have implicit backing types to begin with.

The logic here could also be applied to enums, so that enum { ... } is disallowed in favour of enum(T) { ... }. That might also imply disallowing union(enum) { ... }in favour of union(enum(T)) { ... }. This proposal does not propose these changes -- I personally think they would definitely be going too far, so if we do want to consider that change, it should be a separate proposal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingImplementing this issue could cause existing code to no longer compile or have different behavior.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions