authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-21 23:50:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-21 23:50:20-07:00
logc2a9a591f6f746c777800e4394ca0ee875be3688
treefaf0babedbd9bbbf8c107b3653422e7927de9524
parent9dc98fbabbd5e91622d2459ec6265a8dae2405b8

Sema: fix union auto-enum numbering


2 files changed, 22 insertions(+), 14 deletions(-)

src/Sema.zig+21-9
......@@ -17526,6 +17526,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
1752617526 extra_index += bit_bags_count;
1752717527 var cur_bit_bag: u32 = undefined;
1752817528 var field_i: u32 = 0;
17529 var last_tag_val: ?Value = null;
1752917530 while (field_i < fields_len) : (field_i += 1) {
1753017531 if (field_i % fields_per_u32 == 0) {
1753117532 cur_bit_bag = zir.extra[bit_bag_index];
......@@ -17566,15 +17567,26 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
1756617567 } else .none;
1756717568
1756817569 if (enum_value_map) |map| {
17569 const tag_src = src; // TODO better source location
17570 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);
17571 const val = try sema.resolveConstValue(&block_scope, tag_src, coerced);
17572
17573 // This puts the memory into the union arena, not the enum arena, but
17574 // it is OK since they share the same lifetime.
17575 const copied_val = try val.copy(decl_arena_allocator);
17576
17577 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });
17570 if (tag_ref != .none) {
17571 const tag_src = src; // TODO better source location
17572 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src);
17573 const val = try sema.resolveConstValue(&block_scope, tag_src, coerced);
17574 last_tag_val = val;
17575
17576 // This puts the memory into the union arena, not the enum arena, but
17577 // it is OK since they share the same lifetime.
17578 const copied_val = try val.copy(decl_arena_allocator);
17579 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });
17580 } else {
17581 const val = if (last_tag_val) |val|
17582 try val.intAdd(Value.one, sema.arena)
17583 else
17584 Value.zero;
17585 last_tag_val = val;
17586
17587 const copied_val = try val.copy(decl_arena_allocator);
17588 map.putAssumeCapacityContext(copied_val, {}, .{ .ty = int_tag_ty });
17589 }
1757817590 }
1757917591
1758017592 // This string needs to outlive the ZIR code.
test/behavior/union.zig+1-5
......@@ -495,7 +495,7 @@ test "tagged union with all void fields but a meaningful tag" {
495495}
496496
497497test "union(enum(u32)) with specified and unspecified tag values" {
498 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
499499
500500 comptime try expect(Tag(Tag(MultipleChoice2)) == u32);
501501 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
......@@ -558,8 +558,6 @@ const PartialInstWithPayload = union(enum) {
558558};
559559
560560test "union with only 1 field casted to its enum type which has enum value specified" {
561 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
562
563561 const Literal = union(enum) {
564562 Number: f64,
565563 Bool: bool,
......@@ -640,8 +638,6 @@ fn Setter(attr: Attribute) type {
640638}
641639
642640test "return union init with void payload" {
643 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
644
645641 const S = struct {
646642 fn entry() !void {
647643 try expect(func().state == State.one);