From 776caaf99927181a2bb135afa9b502014782691c Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 28 Aug 2022 13:37:38 +0300 Subject: [PATCH] Sema: fix handling of non-standard int types in empty non-exhaustive enums Closes #12649 --- src/Sema.zig | 15 +++------------ src/print_zir.zig | 10 +++++----- test/behavior/enum.zig | 5 +++++ 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 17d3b02da3..586f1b2ee8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2497,18 +2497,6 @@ fn zirEnumDecl( extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl); const body = sema.code.extra[extra_index..][0..body_len]; - if (fields_len == 0) { - assert(body.len == 0); - if (tag_type_ref != .none) { - const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); - if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) { - return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)}); - } - enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); - enum_obj.tag_ty_inferred = false; - } - return decl_val; - } extra_index += body.len; const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; @@ -2566,6 +2554,9 @@ fn zirEnumDecl( } enum_obj.tag_ty = try ty.copy(decl_arena_allocator); enum_obj.tag_ty_inferred = false; + } else if (fields_len == 0) { + enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0); + enum_obj.tag_ty_inferred = true; } else { const bits = std.math.log2_int_ceil(usize, fields_len); enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits); diff --git a/src/print_zir.zig b/src/print_zir.zig index 579a7970b7..f315d7f014 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -1721,13 +1721,13 @@ const Writer = struct { const body = self.code.extra[extra_index..][0..body_len]; extra_index += body.len; + const prev_parent_decl_node = self.parent_decl_node; + if (src_node) |off| self.parent_decl_node = self.relativeToNodeIndex(off); + try self.writeBracedDecl(stream, body); if (fields_len == 0) { - assert(body.len == 0); - try stream.writeAll("{}, {})"); + try stream.writeAll(", {})"); + self.parent_decl_node = prev_parent_decl_node; } else { - const prev_parent_decl_node = self.parent_decl_node; - if (src_node) |off| self.parent_decl_node = self.relativeToNodeIndex(off); - try self.writeBracedDecl(stream, body); try stream.writeAll(", {\n"); self.indent += 2; diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 9e96163cc0..517414780b 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1170,3 +1170,8 @@ test "switch on an extern enum with negative value" { Foo.Bar => return, } } + +test "Non-exhaustive enum with nonstandard int size behaves correctly" { + const E = enum(u15) { _ }; + try expect(@sizeOf(E) == @sizeOf(u15)); +}