authorgravatar for 14016168+silversquirl@users.noreply.github.comSilver <14016168+silversquirl@users.noreply.github.com> 2025-09-18 05:39:47+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-09-17 21:39:47-07:00
log65a6bf1267770c4d27785cd1fbfa9fb1e5dc30c9
tree70e4980ce40984ce21104d052c8f6df792a0c92e
parent220c6795233bfdc9b93dfb3364b21705b1e6c903
signaturebadge-check Signed by PGP key B5690EEEBB952194

fix handling of comptime-only union fields in `Type.getUnionLayout` (#25182)

Fixes #25180

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

src/Type.zig+11-9
...@@ -3914,15 +3914,17 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)...@@ -3914,15 +3914,17 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
3914 explicit_align3914 explicit_align
3915 else3915 else
3916 field_ty.abiAlignment(zcu);3916 field_ty.abiAlignment(zcu);
3917 const field_size = field_ty.abiSize(zcu);3917 if (field_ty.hasRuntimeBits(zcu)) {
3918 if (field_size > payload_size) {3918 const field_size = field_ty.abiSize(zcu);
3919 payload_size = field_size;3919 if (field_size > payload_size) {
3920 biggest_field = @intCast(field_index);3920 payload_size = field_size;
3921 }3921 biggest_field = @intCast(field_index);
3922 if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {3922 }
3923 most_aligned_field = @intCast(field_index);3923 if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
3924 most_aligned_field_align = field_align;3924 most_aligned_field = @intCast(field_index);
3925 most_aligned_field_size = field_size;3925 most_aligned_field_align = field_align;
3926 most_aligned_field_size = field_size;
3927 }
3926 }3928 }
3927 payload_align = payload_align.max(field_align);3929 payload_align = payload_align.max(field_align);
3928 }3930 }
test/behavior/union.zig+18
...@@ -2325,3 +2325,21 @@ test "initialize empty field of union inside comptime-known struct constant" {...@@ -2325,3 +2325,21 @@ test "initialize empty field of union inside comptime-known struct constant" {
2325 const val: Wrapper = .{ .inner = .{ .none = {} } };2325 const val: Wrapper = .{ .inner = .{ .none = {} } };
2326 comptime assert(val.inner.none == {});2326 comptime assert(val.inner.none == {});
2327}2327}
2328
2329test "union with function body field" {
2330 const U = union {
2331 f: fn () void,
2332 fn foo() void {}
2333 fn bar() void {}
2334 };
2335 const x: U = .{ .f = U.foo };
2336 try std.testing.expect(x.f == U.foo);
2337 x.f();
2338
2339 comptime var y: U = .{ .f = U.bar };
2340 try std.testing.expect(y.f == U.bar);
2341 y.f();
2342 y.f = U.foo;
2343 try std.testing.expect(y.f == U.foo);
2344 y.f();
2345}