authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-26 21:36:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-26 21:36:12-07:00
logf41b9cdb6d7f954495ffca168108ddd38bf27353
tree3e7855187364efa94d4492eb19b79599b8d46926
parent629a54c711c0a71381ea1e5b1a62e5fcc986e048

Sema: fix enum tag type not initialized when 0 fields


3 files changed, 62 insertions(+), 59 deletions(-)

src/Sema.zig+7-1
......@@ -1759,6 +1759,11 @@ fn zirEnumDecl(
17591759 const body = sema.code.extra[extra_index..][0..body_len];
17601760 if (fields_len == 0) {
17611761 assert(body.len == 0);
1762 if (tag_type_ref != .none) {
1763 // TODO better source location
1764 const ty = try sema.resolveType(block, src, tag_type_ref);
1765 enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator);
1766 }
17621767 try new_decl.finalizeNewArena(&new_decl_arena);
17631768 return sema.analyzeDeclVal(block, src, new_decl);
17641769 }
......@@ -1810,7 +1815,8 @@ fn zirEnumDecl(
18101815 const tag_ty = blk: {
18111816 if (tag_type_ref != .none) {
18121817 // TODO better source location
1813 break :blk try sema.resolveType(block, src, tag_type_ref);
1818 const ty = try sema.resolveType(block, src, tag_type_ref);
1819 break :blk try ty.copy(new_decl_arena_allocator);
18141820 }
18151821 const bits = std.math.log2_int_ceil(usize, fields_len);
18161822 break :blk try Type.Tag.int_unsigned.create(new_decl_arena_allocator, bits);
test/behavior/enum.zig+53
......@@ -646,3 +646,56 @@ test "non-exhaustive enum" {
646646 try S.doTheTest(52);
647647 comptime try S.doTheTest(52);
648648}
649
650test "empty non-exhaustive enum" {
651 const S = struct {
652 const E = enum(u8) { _ };
653
654 fn doTheTest(y: u8) !void {
655 var e = @intToEnum(E, y);
656 try expect(switch (e) {
657 _ => true,
658 });
659 try expect(@enumToInt(e) == y);
660
661 try expect(@typeInfo(E).Enum.fields.len == 0);
662 try expect(@typeInfo(E).Enum.is_exhaustive == false);
663 }
664 };
665 try S.doTheTest(42);
666 comptime try S.doTheTest(42);
667}
668
669test "single field non-exhaustive enum" {
670 const S = struct {
671 const E = enum(u8) { a, _ };
672 fn doTheTest(y: u8) !void {
673 var e: E = .a;
674 try expect(switch (e) {
675 .a => true,
676 _ => false,
677 });
678 e = @intToEnum(E, 12);
679 try expect(switch (e) {
680 .a => false,
681 _ => true,
682 });
683
684 try expect(switch (e) {
685 .a => false,
686 else => true,
687 });
688 e = .a;
689 try expect(switch (e) {
690 .a => true,
691 else => false,
692 });
693
694 try expect(@enumToInt(@intToEnum(E, y)) == y);
695 try expect(@typeInfo(E).Enum.fields.len == 1);
696 try expect(@typeInfo(E).Enum.is_exhaustive == false);
697 }
698 };
699 try S.doTheTest(23);
700 comptime try S.doTheTest(23);
701}
test/behavior/enum_stage1.zig+2-58
......@@ -2,64 +2,6 @@ const expect = @import("std").testing.expect;
22const mem = @import("std").mem;
33const Tag = @import("std").meta.Tag;
44
5test "empty non-exhaustive enum" {
6 const S = struct {
7 const E = enum(u8) {
8 _,
9 };
10 fn doTheTest(y: u8) !void {
11 var e = @intToEnum(E, y);
12 try expect(switch (e) {
13 _ => true,
14 });
15 try expect(@enumToInt(e) == y);
16
17 try expect(@typeInfo(E).Enum.fields.len == 0);
18 try expect(@typeInfo(E).Enum.is_exhaustive == false);
19 }
20 };
21 try S.doTheTest(42);
22 comptime try S.doTheTest(42);
23}
24
25test "single field non-exhaustive enum" {
26 const S = struct {
27 const E = enum(u8) { a, _ };
28 fn doTheTest(y: u8) !void {
29 var e: E = .a;
30 try expect(switch (e) {
31 .a => true,
32 _ => false,
33 });
34 e = @intToEnum(E, 12);
35 try expect(switch (e) {
36 .a => false,
37 _ => true,
38 });
39
40 try expect(switch (e) {
41 .a => false,
42 else => true,
43 });
44 e = .a;
45 try expect(switch (e) {
46 .a => true,
47 else => false,
48 });
49
50 try expect(@enumToInt(@intToEnum(E, y)) == y);
51 try expect(@typeInfo(E).Enum.fields.len == 1);
52 try expect(@typeInfo(E).Enum.is_exhaustive == false);
53 }
54 };
55 try S.doTheTest(23);
56 comptime try S.doTheTest(23);
57}
58
59const Bar = enum { A, B, C, D };
60
61const Number = enum { Zero, One, Two, Three, Four };
62
635test "@tagName" {
646 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
657 comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
......@@ -304,6 +246,8 @@ test "enum with one member and custom tag type" {
304246 try expect(@enumToInt(E2.One) == 2);
305247}
306248
249const Bar = enum { A, B, C, D };
250
307251test "enum literal casting to optional" {
308252 var bar: ?Bar = undefined;
309253 bar = .B;