| author | |
| committer | |
| log | eb7d36ae0d240b8ef5421703e613d164cf691d8d |
| tree | 8ff235e5c307160217500b7ed7e51906dc06f3b5 |
| parent | 742abc71c75a3448526c14980d0daae1c6ff8f96 |
* Allow comptime_int as explicit enum tag type
Closes #29973 files changed, 38 insertions(+), 9 deletions(-)
src/analyze.cpp+3-6| ... | ... | @@ -2406,8 +2406,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2406 | 2406 | ZigType *tag_int_type; |
| 2407 | 2407 | if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { |
| 2408 | 2408 | tag_int_type = get_c_int_type(g, CIntTypeInt); |
| 2409 | } else if (enum_type->data.enumeration.layout == ContainerLayoutAuto && field_count == 1) { | |
| 2410 | tag_int_type = g->builtin_types.entry_num_lit_int; | |
| 2411 | 2409 | } else { |
| 2412 | 2410 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| 2413 | 2411 | } |
| ... | ... | @@ -2420,7 +2418,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2420 | 2418 | ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); |
| 2421 | 2419 | if (type_is_invalid(wanted_tag_int_type)) { |
| 2422 | 2420 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2423 | } else if (wanted_tag_int_type->id != ZigTypeIdInt) { | |
| 2421 | } else if (wanted_tag_int_type->id != ZigTypeIdInt && | |
| 2422 | wanted_tag_int_type->id != ZigTypeIdComptimeInt) { | |
| 2424 | 2423 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; |
| 2425 | 2424 | add_node_error(g, decl_node->data.container_decl.init_arg_expr, |
| 2426 | 2425 | 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) { |
| 2806 | 2805 | union_type->data.unionation.resolve_status = ResolveStatusInvalid; |
| 2807 | 2806 | return ErrorSemanticAnalyzeFail; |
| 2808 | 2807 | } |
| 2809 | if (tag_int_type->id != ZigTypeIdInt) { | |
| 2808 | if (tag_int_type->id != ZigTypeIdInt && tag_int_type->id != ZigTypeIdComptimeInt) { | |
| 2810 | 2809 | add_node_error(g, enum_type_node, |
| 2811 | 2810 | buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); |
| 2812 | 2811 | union_type->data.unionation.resolve_status = ResolveStatusInvalid; |
| 2813 | 2812 | return ErrorSemanticAnalyzeFail; |
| 2814 | 2813 | } |
| 2815 | } else if (auto_layout && field_count == 1) { | |
| 2816 | tag_int_type = g->builtin_types.entry_num_lit_int; | |
| 2817 | 2814 | } else { |
| 2818 | 2815 | tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); |
| 2819 | 2816 | } |
test/stage1/behavior/enum.zig+16| ... | ... | @@ -1014,3 +1014,19 @@ test "enum with one member and u1 tag type @enumToInt" { |
| 1014 | 1014 | }; |
| 1015 | 1015 | expect(@enumToInt(Enum.Test) == 0); |
| 1016 | 1016 | } |
| 1017 | ||
| 1018 | test "enum with comptime_int tag type" { | |
| 1019 | const Enum = enum(comptime_int) { | |
| 1020 | One = 3, | |
| 1021 | Two = 2, | |
| 1022 | Three = 1, | |
| 1023 | }; | |
| 1024 | comptime expect(@TagType(Enum) == comptime_int); | |
| 1025 | } | |
| 1026 | ||
| 1027 | test "enum with one member default to u0 tag type" { | |
| 1028 | const E0 = enum { | |
| 1029 | X, | |
| 1030 | }; | |
| 1031 | comptime expect(@TagType(E0) == u0); | |
| 1032 | } |
test/stage1/behavior/union.zig+19-3| ... | ... | @@ -324,7 +324,7 @@ test "union with only 1 field casted to its enum type" { |
| 324 | 324 | |
| 325 | 325 | var e = Expr{ .Literal = Literal{ .Bool = true } }; |
| 326 | 326 | const Tag = @TagType(Expr); |
| 327 | comptime expect(@TagType(Tag) == comptime_int); | |
| 327 | comptime expect(@TagType(Tag) == u0); | |
| 328 | 328 | var t = Tag(e); |
| 329 | 329 | expect(t == Expr.Literal); |
| 330 | 330 | } |
| ... | ... | @@ -335,7 +335,7 @@ test "union with only 1 field casted to its enum type which has enum value speci |
| 335 | 335 | Bool: bool, |
| 336 | 336 | }; |
| 337 | 337 | |
| 338 | const Tag = enum { | |
| 338 | const Tag = enum(comptime_int) { | |
| 339 | 339 | Literal = 33, |
| 340 | 340 | }; |
| 341 | 341 | |
| ... | ... | @@ -469,7 +469,7 @@ test "union no tag with struct member" { |
| 469 | 469 | } |
| 470 | 470 | |
| 471 | 471 | fn testComparison() void { |
| 472 | var x = Payload{.A = 42}; | |
| 472 | var x = Payload{ .A = 42 }; | |
| 473 | 473 | expect(x == .A); |
| 474 | 474 | expect(x != .B); |
| 475 | 475 | expect(x != .C); |
| ... | ... | @@ -494,3 +494,19 @@ test "packed union generates correctly aligned LLVM type" { |
| 494 | 494 | }; |
| 495 | 495 | foo[0].f1(); |
| 496 | 496 | } |
| 497 | ||
| 498 | test "union with one member defaults to u0 tag type" { | |
| 499 | const U0 = union(enum) { | |
| 500 | X: u32, | |
| 501 | }; | |
| 502 | comptime expect(@TagType(@TagType(U0)) == u0); | |
| 503 | } | |
| 504 | ||
| 505 | test "union with comptime_int tag" { | |
| 506 | const Union = union(enum(comptime_int)) { | |
| 507 | X: u32, | |
| 508 | Y: u16, | |
| 509 | Z: u8, | |
| 510 | }; | |
| 511 | comptime expect(@TagType(@TagType(Union)) == comptime_int); | |
| 512 | } |