From f2d13f6d074139c01184e170fe24127a2d9db944 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Tue, 9 Jun 2026 18:58:47 -0700 Subject: [PATCH] Sema: preserve union alignment to field on switch --- src/Sema.zig | 15 ++++++--------- test/behavior/switch.zig | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index d5ca3362eff259d909c3cbd8236923ceab9291c6..b27d452b7dd6b4223c569bc0b22d838e6adeda16 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12083,15 +12083,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion( const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); const payload_ref: Air.Inst.Ref = payload_ref: { if (capture_by_ref) { - const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu); - const ptr_field_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = operand_ptr_info.flags.is_const, - .is_volatile = operand_ptr_info.flags.is_volatile, - .address_space = operand_ptr_info.flags.address_space, - }, - }); + const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt); + if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| { + if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty); + const field_ptr_val = try op_ptr_val.ptrField(field_index, pt); + break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty)); + } break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty); } if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| { diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index e9923bac27db1c6060d3485daed18ac20d271f47..e56da92324e578190ea4119e04b5379abf687c2d 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" { }; } } + +test "union field pointer capture preserves alignment in inline prong" { + const U = union(enum) { + a: u32, + b: u32, + fn doTheTest(u: *align(1) const @This()) !void { + switch (u.*) { + inline .a, .b => |*a_ptr| { + comptime assert(@TypeOf(a_ptr) == *align(1) const u32); + try expect(a_ptr.* == 123); + }, + } + } + }; + try U.doTheTest(&.{ .a = 123 }); + try U.doTheTest(&.{ .b = 123 }); + try comptime U.doTheTest(&.{ .a = 123 }); + try comptime U.doTheTest(&.{ .b = 123 }); +} -- 2.54.0