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(...@@ -2497,18 +2497,6 @@ fn zirEnumDecl(
2497 extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);2497 extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
24982498
2499 const body = sema.code.extra[extra_index..][0..body_len];2499 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 }
2512 extra_index += body.len;2500 extra_index += body.len;
25132501
2514 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;2502 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
...@@ -2566,6 +2554,9 @@ fn zirEnumDecl(...@@ -2566,6 +2554,9 @@ fn zirEnumDecl(
2566 }2554 }
2567 enum_obj.tag_ty = try ty.copy(decl_arena_allocator);2555 enum_obj.tag_ty = try ty.copy(decl_arena_allocator);
2568 enum_obj.tag_ty_inferred = false;2556 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;
2569 } else {2560 } else {
2570 const bits = std.math.log2_int_ceil(usize, fields_len);2561 const bits = std.math.log2_int_ceil(usize, fields_len);
2571 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits);2562 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 {...@@ -1721,13 +1721,13 @@ const Writer = struct {
1721 const body = self.code.extra[extra_index..][0..body_len];1721 const body = self.code.extra[extra_index..][0..body_len];
1722 extra_index += body.len;1722 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);
1724 if (fields_len == 0) {1727 if (fields_len == 0) {
1725 assert(body.len == 0);1728 try stream.writeAll(", {})");
1726 try stream.writeAll("{}, {})");1729 self.parent_decl_node = prev_parent_decl_node;
1727 } else {1730 } 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);
1731 try stream.writeAll(", {\n");1731 try stream.writeAll(", {\n");
17321732
1733 self.indent += 2;1733 self.indent += 2;
test/behavior/enum.zig+5
...@@ -1170,3 +1170,8 @@ test "switch on an extern enum with negative value" {...@@ -1170,3 +1170,8 @@ test "switch on an extern enum with negative value" {
1170 Foo.Bar => return,1170 Foo.Bar => return,
1171 }1171 }
1172}1172}
1173
1174test "Non-exhaustive enum with nonstandard int size behaves correctly" {
1175 const E = enum(u15) { _ };
1176 try expect(@sizeOf(E) == @sizeOf(u15));
1177}