ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.5k stars 2.52k forks source link

@Type() cannot build tagged unions #8114

Open fengb opened 3 years ago

fengb commented 3 years ago

My understanding is that tagged union are created via .layout = .Auto, .tag_type = EnumDefinition, but this currently generates compiler errors indicating this union isn't tagged:

const std = @import("std");

const Broken = @Type(.{
    .Union = .{
        .layout = .Auto,
        .tag_type = enum { temp },
        .fields = &[_]std.builtin.TypeInfo.UnionField{
            .{ .name = "foo", .field_type = void, .alignment = 0 },
        },
        .decls = &.{},
    },
});

comptime {
    // error: switch on union which has no attached enum
    switch (Broken{ .foo = {} }) {
        .foo => {},
    }
}

@g-w1 mentioned that the stage1 compiler is crossreferencing against the wrong condition: https://github.com/ziglang/zig/pull/8069

Interestingly enough, this seems to work if I hijack an existing tagged union:

const Ref = union(enum) {temp};
const Working = blk: {
    var info = @typeInfo(Ref);
    info.Union.tag_type = enum { foo };
    info.Union.fields = &[_]std.builtin.TypeInfo.UnionField{
        .{ .name = "foo", .field_type = void, .alignment = 0 },
    };
    break :blk @Type(info);
};
sh4r1k7 commented 2 years ago

Just ran into this myself and I found that you don't need to hijack an existing type, merely store the type info into a variable then pass it to @Type(t).