Construct auto-tagged union with @Union

How do I construct an auto-tagged union(enum) with @Union?

For example, how do I make this union with @Union?

pub const MyUnion = union(enum) {
    my_void,
    my_u8: u8,
}
test "union building" {
    const MyUnion = @Union(
        .auto,
        null,
        &.{ "my_void", "my_u8" },
        &.{ void, u8 },
        &@splat(.{}),
    );

    var my_union: MyUnion = .my_void;
    _ = &my_union;

    switch (my_union) {
        .my_void => std.testing.expect(true),
        .my_u8 => std.testing.expect(false),
    }
}
src/argparser/test.zig:257:30: error: union 'test.test.union building.MyUnion' has no member named 'my_void'
    var my_union: MyUnion = .my_void;
                            ~^~~~~~~
src/argparser/test.zig:249:21: note: union declared here
    const MyUnion = @Union(

Only tagged unions can be used with switch statements. A union with null ArgType is a bare union.

We must define the Enum type first.

const std = @import("std");
test "union building" {
    const MyUnion = blk: {
        const field_names = [_][]const u8{
            "my_void",
            "my_u8",
        };
        const len = field_names.len;
        const TagInt = @Int(.unsigned, std.math.log2_int_ceil(usize, len));
        comptime var field_values: [len]TagInt = undefined;
        comptime for (0..len) |id| {
            field_values[id] = @intCast(id);
        };
        const E = @Enum(TagInt, .exhaustive, &field_names, &field_values);
        break :blk @Union(
            .auto,
            E,
            &field_names,
            &.{ void, u8 },
            &@splat(.{}),
        );
    };

    var my_union: MyUnion = .my_void;
    _ = &my_union;

    switch (my_union) {
        .my_void => try std.testing.expect(true),
        .my_u8 => try std.testing.expect(false),
    }
}
1 Like