authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-28 13:37:38+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-28 15:41:21+03:00
log776caaf99927181a2bb135afa9b502014782691c
treea67bbeb7166fe7badbed7790024c98c625808e96
parent6aead18ab332a3cf809b5c824d70cdc52f0e5156

Sema: fix handling of non-standard int types in empty non-exhaustive enums

Closes #12649

3 files changed, 13 insertions(+), 17 deletions(-)

src/Sema.zig+3-12
......@@ -2497,18 +2497,6 @@ fn zirEnumDecl(
24972497 extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
24982498
24992499 const body = sema.code.extra[extra_index..][0..body_len];
2500 if (fields_len == 0) {
2501 assert(body.len == 0);
2502 if (tag_type_ref != .none) {
2503 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
2504 if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) {
2505 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});
2506 }
2507 enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator);
2508 enum_obj.tag_ty_inferred = false;
2509 }
2510 return decl_val;
2511 }
25122500 extra_index += body.len;
25132501
25142502 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
......@@ -2566,6 +2554,9 @@ fn zirEnumDecl(
25662554 }
25672555 enum_obj.tag_ty = try ty.copy(decl_arena_allocator);
25682556 enum_obj.tag_ty_inferred = false;
2557 } else if (fields_len == 0) {
2558 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0);
2559 enum_obj.tag_ty_inferred = true;
25692560 } else {
25702561 const bits = std.math.log2_int_ceil(usize, fields_len);
25712562 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits);
src/print_zir.zig+5-5
......@@ -1721,13 +1721,13 @@ const Writer = struct {
17211721 const body = self.code.extra[extra_index..][0..body_len];
17221722 extra_index += body.len;
17231723
1724 const prev_parent_decl_node = self.parent_decl_node;
1725 if (src_node) |off| self.parent_decl_node = self.relativeToNodeIndex(off);
1726 try self.writeBracedDecl(stream, body);
17241727 if (fields_len == 0) {
1725 assert(body.len == 0);
1726 try stream.writeAll("{}, {})");
1728 try stream.writeAll(", {})");
1729 self.parent_decl_node = prev_parent_decl_node;
17271730 } else {
1728 const prev_parent_decl_node = self.parent_decl_node;
1729 if (src_node) |off| self.parent_decl_node = self.relativeToNodeIndex(off);
1730 try self.writeBracedDecl(stream, body);
17311731 try stream.writeAll(", {\n");
17321732
17331733 self.indent += 2;
test/behavior/enum.zig+5
......@@ -1170,3 +1170,8 @@ test "switch on an extern enum with negative value" {
11701170 Foo.Bar => return,
11711171 }
11721172}
1173
1174test "Non-exhaustive enum with nonstandard int size behaves correctly" {
1175 const E = enum(u15) { _ };
1176 try expect(@sizeOf(E) == @sizeOf(u15));
1177}