Convert a non-exhaustive enum to an exhaustive enum

Here’s how you can convert a non-exhaustive enum to an exhaustive one:

const std = @import("std");
const assert = std.debug.assert;

pub fn Exhaustive(@"enum": type) type {
    comptime assert(@typeInfo(@"enum").@"enum".is_exhaustive == false);
    var type_info = @typeInfo(@"enum");
    type_info.@"enum".is_exhaustive = true;
    return @Type(type_info);
}

test {
    const MyEnum = enum(u8) {
        zero,
        one,
        two,
        _,
    };

    const NewEnum = Exhaustive(MyEnum);

    try std.testing.expect(@typeInfo(NewEnum).@"enum".is_exhaustive);
    try std.testing.expectEqual(0, @intFromEnum(NewEnum.zero));
    try std.testing.expectEqual(1, @intFromEnum(NewEnum.one));
    try std.testing.expectEqual(2, @intFromEnum(NewEnum.two));
}

I wonder if there is a way to do it without breaking ZLS?

why bother? Mind explaining that one?

Not strictly required, but for my own taste I like to have less code than more code, so it serves as a reminder to not use it when you don’t have to.

I haven’t really found a way to get ZLS to suggest the enum names when using NewEnum., however when I use something like this it works const val:NewEnum = ., so maybe ZLS’s support for namespace lookups is worse than for typed values.