mirror of
https://github.com/ziglang/zig.git
synced 2026-01-05 21:13:24 +00:00
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
This commit is contained in:
parent
52879b50d9
commit
44f8e6a534
@ -5973,7 +5973,8 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||
}
|
||||
ZigType *field_type = resolve_struct_field_type(g, field);
|
||||
assert(field_type != nullptr);
|
||||
result->data.x_struct.fields[i] = get_the_one_possible_value(g, field_type);
|
||||
copy_const_val(g, result->data.x_struct.fields[i],
|
||||
get_the_one_possible_value(g, field_type));
|
||||
}
|
||||
} else if (result->type->id == ZigTypeIdArray) {
|
||||
// The elements array cannot be left unpopulated
|
||||
@ -5986,7 +5987,20 @@ ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||
ZigValue *elem_val = &result->data.x_array.data.s_none.elements[i];
|
||||
copy_const_val(g, elem_val, get_the_one_possible_value(g, elem_type));
|
||||
}
|
||||
} else if (result->type->id == ZigTypeIdUnion) {
|
||||
// The payload/tag fields cannot be left unpopulated
|
||||
ZigType *union_type = result->type;
|
||||
assert(union_type->data.unionation.src_field_count == 1);
|
||||
TypeUnionField *only_field = &union_type->data.unionation.fields[0];
|
||||
ZigType *field_type = resolve_union_field_type(g, only_field);
|
||||
assert(field_type);
|
||||
bigint_init_unsigned(&result->data.x_union.tag, 0);
|
||||
result->data.x_union.payload = g->pass1_arena->create<ZigValue>();
|
||||
copy_const_val(g, result->data.x_union.payload,
|
||||
get_the_one_possible_value(g, field_type));
|
||||
} else if (result->type->id == ZigTypeIdPointer) {
|
||||
// Make sure nobody can modify the constant value
|
||||
result->data.x_ptr.mut = ConstPtrMutComptimeConst;
|
||||
result->data.x_ptr.special = ConstPtrSpecialRef;
|
||||
result->data.x_ptr.data.ref.pointee = get_the_one_possible_value(g, result->type->data.pointer.child_type);
|
||||
}
|
||||
|
||||
@ -713,3 +713,27 @@ test "switching on non exhaustive union" {
|
||||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "containers with single-field enums" {
|
||||
const S = struct {
|
||||
const A = union(enum) { f1 };
|
||||
const B = union(enum) { f1: void };
|
||||
const C = struct { a: A };
|
||||
const D = struct { a: B };
|
||||
|
||||
fn doTheTest() void {
|
||||
var array1 = [1]A{A{ .f1 = {} }};
|
||||
var array2 = [1]B{B{ .f1 = {} }};
|
||||
expect(array1[0] == .f1);
|
||||
expect(array2[0] == .f1);
|
||||
|
||||
var struct1 = C{ .a = A{ .f1 = {} } };
|
||||
var struct2 = D{ .a = B{ .f1 = {} } };
|
||||
expect(struct1.a == .f1);
|
||||
expect(struct2.a == .f1);
|
||||
}
|
||||
};
|
||||
|
||||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user