#Combining Enums at Comptime

1 messages · Page 1 of 1 (latest)

edgy snow
#

I have two enums that I would like to use separately, but sometimes also as a single enum combining the fields of both.
I tried to use a comptime block to combine the enums, but I get a segfault on zig 0.10.0-dev.4707+209a0d2a8, and an crash with an error message on 0.11.0-dev.4799+8c4faa5f3.

I can make a github issue for this, but I was wondering if this is something anyone else has done successfully?

This is my most minimal example:

const std = @import("std");

pub const CombinedEnum = blk: {
    const numFields = @typeInfo(FirstEnum).Enum.fields.len + @typeInfo(SecondEnum).Enum.fields.len;
    comptime var fields: [numFields]std.builtin.Type.EnumField = undefined;

    comptime var index = 0;
    for (@typeInfo(FirstEnum).Enum.fields) |field| {
        fields[index] = field;
        index += 1;
    }

    for (@typeInfo(SecondEnum).Enum.fields) |field| {
        fields[index] = field;
        index += 1;
    }

    const enumInfo = std.builtin.Type.Enum{
        .layout = std.builtin.Type.ContainerLayout.Auto,
        .tag_type = u8,
        .fields = &fields,
        .decls = &[0]std.builtin.Type.Declaration{},
        .is_exhaustive = true,
    };

    break :blk @Type(std.builtin.Type{ .Enum = enumInfo });
};

pub const FirstEnum = enum {
    field0,
};

pub const SecondEnum = enum {
    field1,
};

pub fn main() anyerror!void {
    std.debug.print("startup\n", .{});
    const first = CombinedEnum.field0;
    const second = CombinedEnum.field1;
    std.debug.print("first = {}, second = {}\n", .{ first, second });
}

Thank you!

#

The error message is too long to post, but starts with:

thread 93684 panic: reached unreachable code
/home/REDACTED/programs/zig/lib/std/debug.zig:278:14: 0x55d3389f8156 in std.debug.assert (zig2)
    if (!ok) unreachable; // assertion failure
             ^

This is an assert in array_hash_map.zig on line 863, "assert(!result.found_existing);" within putAssumeCapacityNoClobberContext.

edgy snow
#

The problem was that I intended the enum variants to be unique, but I was reusing their values without modifying them, so field0 and field1 end up with the same value.

#

This shouldn't crash the compiler, so the issue wasn't closed, but it wasn't what I was intending to do. I can go forward with my code with this change.