authorgravatar for sinon@vortan.devDavid Rubin <sinon@vortan.dev> 2026-06-09 18:58:47-07:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-18 16:42:32+02:00
logf2d13f6d074139c01184e170fe24127a2d9db944
tree5da6944e61cc89d16ee0bfa06c1c520a18084407
parent805e51389ba89ad1460efafcf2e0a373008d72bc

Sema: preserve union alignment to field on switch


2 files changed, 25 insertions(+), 9 deletions(-)

src/Sema.zig+6-9
...@@ -12083,15 +12083,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion(...@@ -12083,15 +12083,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion(
12083 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);12083 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
12084 const payload_ref: Air.Inst.Ref = payload_ref: {12084 const payload_ref: Air.Inst.Ref = payload_ref: {
12085 if (capture_by_ref) {12085 if (capture_by_ref) {
12086 const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu);12086 const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt);
12087 const ptr_field_ty = try pt.ptrType(.{12087 if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| {
12088 .child = field_ty.toIntern(),12088 if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty);
12089 .flags = .{12089 const field_ptr_val = try op_ptr_val.ptrField(field_index, pt);
12090 .is_const = operand_ptr_info.flags.is_const,12090 break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty));
12091 .is_volatile = operand_ptr_info.flags.is_volatile,12091 }
12092 .address_space = operand_ptr_info.flags.address_space,
12093 },
12094 });
12095 break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty);12092 break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty);
12096 }12093 }
12097 if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| {12094 if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| {
test/behavior/switch.zig+19
...@@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" {...@@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" {
1574 };1574 };
1575 }1575 }
1576}1576}
1577
1578test "union field pointer capture preserves alignment in inline prong" {
1579 const U = union(enum) {
1580 a: u32,
1581 b: u32,
1582 fn doTheTest(u: *align(1) const @This()) !void {
1583 switch (u.*) {
1584 inline .a, .b => |*a_ptr| {
1585 comptime assert(@TypeOf(a_ptr) == *align(1) const u32);
1586 try expect(a_ptr.* == 123);
1587 },
1588 }
1589 }
1590 };
1591 try U.doTheTest(&.{ .a = 123 });
1592 try U.doTheTest(&.{ .b = 123 });
1593 try comptime U.doTheTest(&.{ .a = 123 });
1594 try comptime U.doTheTest(&.{ .b = 123 });
1595}