From eb7d36ae0d240b8ef5421703e613d164cf691d8d Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 13 Sep 2019 12:12:12 +0200 Subject: [PATCH] Make single-element enum default to u0 * Allow comptime_int as explicit enum tag type Closes #2997 --- src/analyze.cpp | 9 +++------ test/stage1/behavior/enum.zig | 16 ++++++++++++++++ test/stage1/behavior/union.zig | 22 +++++++++++++++++++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 946bbd17ae..58ec0cf133 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2406,8 +2406,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { ZigType *tag_int_type; if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { tag_int_type = get_c_int_type(g, CIntTypeInt); - } else if (enum_type->data.enumeration.layout == ContainerLayoutAuto && field_count == 1) { - tag_int_type = g->builtin_types.entry_num_lit_int; } else { tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); } @@ -2420,7 +2418,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); if (type_is_invalid(wanted_tag_int_type)) { enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; - } else if (wanted_tag_int_type->id != ZigTypeIdInt) { + } else if (wanted_tag_int_type->id != ZigTypeIdInt && + wanted_tag_int_type->id != ZigTypeIdComptimeInt) { enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; add_node_error(g, decl_node->data.container_decl.init_arg_expr, buf_sprintf("expected integer, found '%s'", buf_ptr(&wanted_tag_int_type->name))); @@ -2806,14 +2805,12 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } - if (tag_int_type->id != ZigTypeIdInt) { + if (tag_int_type->id != ZigTypeIdInt && tag_int_type->id != ZigTypeIdComptimeInt) { add_node_error(g, enum_type_node, buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } - } else if (auto_layout && field_count == 1) { - tag_int_type = g->builtin_types.entry_num_lit_int; } else { tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); } diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig index 3f6b2b7bd3..6084dad3cb 100644 --- a/test/stage1/behavior/enum.zig +++ b/test/stage1/behavior/enum.zig @@ -1014,3 +1014,19 @@ test "enum with one member and u1 tag type @enumToInt" { }; expect(@enumToInt(Enum.Test) == 0); } + +test "enum with comptime_int tag type" { + const Enum = enum(comptime_int) { + One = 3, + Two = 2, + Three = 1, + }; + comptime expect(@TagType(Enum) == comptime_int); +} + +test "enum with one member default to u0 tag type" { + const E0 = enum { + X, + }; + comptime expect(@TagType(E0) == u0); +} diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig index 21308b0ea2..75b01164f8 100644 --- a/test/stage1/behavior/union.zig +++ b/test/stage1/behavior/union.zig @@ -324,7 +324,7 @@ test "union with only 1 field casted to its enum type" { var e = Expr{ .Literal = Literal{ .Bool = true } }; const Tag = @TagType(Expr); - comptime expect(@TagType(Tag) == comptime_int); + comptime expect(@TagType(Tag) == u0); var t = Tag(e); expect(t == Expr.Literal); } @@ -335,7 +335,7 @@ test "union with only 1 field casted to its enum type which has enum value speci Bool: bool, }; - const Tag = enum { + const Tag = enum(comptime_int) { Literal = 33, }; @@ -469,7 +469,7 @@ test "union no tag with struct member" { } fn testComparison() void { - var x = Payload{.A = 42}; + var x = Payload{ .A = 42 }; expect(x == .A); expect(x != .B); expect(x != .C); @@ -494,3 +494,19 @@ test "packed union generates correctly aligned LLVM type" { }; foo[0].f1(); } + +test "union with one member defaults to u0 tag type" { + const U0 = union(enum) { + X: u32, + }; + comptime expect(@TagType(@TagType(U0)) == u0); +} + +test "union with comptime_int tag" { + const Union = union(enum(comptime_int)) { + X: u32, + Y: u16, + Z: u8, + }; + comptime expect(@TagType(@TagType(Union)) == comptime_int); +}