Skip to content

Allow explicit null packing optimization in non-exhaustive and sized enums #12524

@sno2

Description

@sno2

Hello, it would be great if we would allow explicitly setting a value for null on an enum to allow for setting the value of it when the enum is null. The optimization is similar to the nullable pointer optimization which allows null to be coerced to null pointers as 0. The following syntax can be used and is non-breaking as parsing fails on the current version of Zig:

const Person = enum (u8) {
  null = 0,
  John,
  James,
  Jack,
  _,
}:

The null variant must have an explicit initializer so as to not confuse it with a regular variant. I am not sure, but it may also be a good idea to limit this variant to non-exhaustive sized enums because the optimization could technically be possible by default on regular enums as the ABI is unspecified.

When you specify a null variant, it is impossible to construct the null via that enum itself (e.g. through alias):

Person.null; // syntax error anyways
Person.@"null"; // this would actually try to access a variant for the literal string "null" so it may fail or pass but it would never actually mean the null variant

The null variant only has meaning for an optional type which contains the enum. In which case, the option part is packed and any time null is assigned to the optional type it will be set to the value of the null variant. This allows for far more beautiful DX when using the optional enum type.

const Person = enum (u32) {
    null = 0,
    John,
    James,
    Jack,
    _
};

const MaybePerson = ?Person;

const foo: MaybePerson = null;
std.debug.print("{}\n", .{@enumToInt(foo)}); // 0 - the value specified

std.debug.print("{}\n", .{@sizeOf(Person)}); // 1
std.debug.print("{}\n", .{@sizeOf(MaybePerson)}); // 1 - successfully packed using the null variant

A use-case I have for this currently is for packing the optional values of garbage-collected references which are secretly indices using a null tag to stay in u32 even when it's optional. I have been just explicitly naming the tag but this means I cannot use the other amazing syntatic features of optional types such as nullable if expressions and orelse.

Metadata

Metadata

Assignees

No one assigned

    Labels

    optimizationproposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions