authorgravatar for rmehri01@tutamail.comRyan Mehri <rmehri01@tutamail.com> 2026-06-17 21:46:38-04:00
committergravatar for justusk@noreply.codeberg.orgJustus Klausecker <justusk@noreply.codeberg.org> 2026-06-18 11:41:36+02:00
log14bc6f5917ae94902cdf209e3ac9af908b506795
tree45c077c272990a11992103bbdb086851f03b6642
parent46a750a006d90120feddcf0f0b9a0b5db9e222be

Sema: check for undefined values in zirArrayCat

Right now, when an undefined tuple value is passed to zirArrayCat, it will call `elemValue`, which will incorrectly try to produce a undef value of the child type (of which there is none) and then panics. This adds a check for an undef value first to produce an undef elem value of the correct resolved type.

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

src/Sema.zig+4-2
......@@ -13479,7 +13479,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1347913479 while (elem_i < lhs_len) : (elem_i += 1) {
1348013480 const lhs_elem_i = elem_i;
1348113481 const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null;
13482 const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i);
13482 const elem_val = elem_default_val orelse
13483 if (lhs_sub_val.isUndef(zcu)) try pt.undefValue(resolved_elem_ty) else try lhs_sub_val.elemValue(pt, lhs_elem_i);
1348313484 const operand_src = block.src(.{ .array_cat_lhs = .{
1348413485 .array_cat_offset = inst_data.src_node,
1348513486 .elem_index = elem_i,
......@@ -13491,7 +13492,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1349113492 while (elem_i < result_len) : (elem_i += 1) {
1349213493 const rhs_elem_i = elem_i - lhs_len;
1349313494 const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null;
13494 const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i);
13495 const elem_val = elem_default_val orelse
13496 if (rhs_sub_val.isUndef(zcu)) try pt.undefValue(resolved_elem_ty) else try rhs_sub_val.elemValue(pt, rhs_elem_i);
1349513497 const operand_src = block.src(.{ .array_cat_rhs = .{
1349613498 .array_cat_offset = inst_data.src_node,
1349713499 .elem_index = @intCast(rhs_elem_i),
test/behavior/array.zig+18
......@@ -98,6 +98,24 @@ test "array concat with tuple" {
9898 }
9999}
100100
101test "array concat with undefined tuple" {
102 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
103
104 {
105 const array: [2]u64 = .{ 1, 2 };
106 var seq = array ++ @as(struct { u32, u16 }, undefined);
107 seq[2] = 3;
108 seq[3] = 4;
109 try std.testing.expectEqualSlices(u64, &.{ 1, 2, 3, 4 }, &seq);
110 }
111 {
112 const array: [2]u64 = undefined;
113 var seq = @as(struct { u32, u16 }, undefined) ++ array;
114 for (&seq, 1..) |*s, i| s.* = i;
115 try std.testing.expectEqualSlices(u64, &.{ 1, 2, 3, 4 }, &seq);
116 }
117}
118
101119test "array init with concat" {
102120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
103121