authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-10-21 15:35:40+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-21 22:42:03-04:00
log44f8e6a534bd2977c741afdbf5ba9df49bde0fd9
tree2d7274179977704d5bd24074b6f9306518da14de
parent52879b50d9fe221c46e62e11c6815da64c70638e

stage1: Fix edge case in Union ZigValue generation

Unions that passed the one_possible_value check were incorrectly generated, none of their internal fields were initialized. Fixes #6758

2 files changed, 39 insertions(+), 1 deletions(-)

src/stage1/analyze.cpp+15-1
...@@ -5973,7 +5973,8 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5973,7 +5973,8 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5973 }5973 }
5974 ZigType *field_type = resolve_struct_field_type(g, field);5974 ZigType *field_type = resolve_struct_field_type(g, field);
5975 assert(field_type != nullptr);5975 assert(field_type != nullptr);
5976 result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);5976 copy_const_val(g, result->data.x_struct.fields[i],
5977 get_the_one_possible_value(g, field_type));
5977 }5978 }
5978 } else if (result->type->id == ZigTypeIdArray) {5979 } else if (result->type->id == ZigTypeIdArray) {
5979 // The elements array cannot be left unpopulated5980 // The elements array cannot be left unpopulated
...@@ -5986,7 +5987,20 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5986,7 +5987,20 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5986 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];5987 ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
5987 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));5988 copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
5988 }5989 }
5990 } else if (result->type->id == ZigTypeIdUnion) {
5991 // The payload/tag fields cannot be left unpopulated
5992 ZigType *union_type = result->type;
5993 assert(union_type->data.unionation.src_field_count == 1);
5994 TypeUnionField *only_field = &union_type->data.unionation.fields[0];
5995 ZigType *field_type = resolve_union_field_type(g, only_field);
5996 assert(field_type);
5997 bigint_init_unsigned(&result->data.x_union.tag, 0);
5998 result->data.x_union.payload = g->pass1_arena->create<ZigValue>();
5999 copy_const_val(g, result->data.x_union.payload,
6000 get_the_one_possible_value(g, field_type));
5989 } else if (result->type->id == ZigTypeIdPointer) {6001 } else if (result->type->id == ZigTypeIdPointer) {
6002 // Make sure nobody can modify the constant value
6003 result->data.x_ptr.mut = ConstPtrMutComptimeConst;
5990 result->data.x_ptr.special = ConstPtrSpecialRef;6004 result->data.x_ptr.special = ConstPtrSpecialRef;
5991 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);6005 result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
5992 }6006 }
test/stage1/behavior/union.zig+24
...@@ -713,3 +713,27 @@ test "switching on non exhaustive union" {...@@ -713,3 +713,27 @@ test "switching on non exhaustive union" {
713 S.doTheTest();713 S.doTheTest();
714 comptime S.doTheTest();714 comptime S.doTheTest();
715}715}
716
717test "containers with single-field enums" {
718 const S = struct {
719 const A = union(enum) { f1 };
720 const B = union(enum) { f1: void };
721 const C = struct { a: A };
722 const D = struct { a: B };
723
724 fn doTheTest() void {
725 var array1 = [1]A{A{ .f1 = {} }};
726 var array2 = [1]B{B{ .f1 = {} }};
727 expect(array1[0] == .f1);
728 expect(array2[0] == .f1);
729
730 var struct1 = C{ .a = A{ .f1 = {} } };
731 var struct2 = D{ .a = B{ .f1 = {} } };
732 expect(struct1.a == .f1);
733 expect(struct2.a == .f1);
734 }
735 };
736
737 S.doTheTest();
738 comptime S.doTheTest();
739}