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

Fixes #25180
This commit is contained in:
Silver 2025-09-18 05:39:47 +01:00 committed by GitHub
parent 220c679523
commit 65a6bf1267
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 29 additions and 9 deletions

View File

@ -3914,15 +3914,17 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
explicit_align
else
field_ty.abiAlignment(zcu);
const field_size = field_ty.abiSize(zcu);
if (field_size > payload_size) {
payload_size = field_size;
biggest_field = @intCast(field_index);
}
if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
most_aligned_field = @intCast(field_index);
most_aligned_field_align = field_align;
most_aligned_field_size = field_size;
if (field_ty.hasRuntimeBits(zcu)) {
const field_size = field_ty.abiSize(zcu);
if (field_size > payload_size) {
payload_size = field_size;
biggest_field = @intCast(field_index);
}
if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
most_aligned_field = @intCast(field_index);
most_aligned_field_align = field_align;
most_aligned_field_size = field_size;
}
}
payload_align = payload_align.max(field_align);
}

View File

@ -2325,3 +2325,21 @@ test "initialize empty field of union inside comptime-known struct constant" {
const val: Wrapper = .{ .inner = .{ .none = {} } };
comptime assert(val.inner.none == {});
}
test "union with function body field" {
const U = union {
f: fn () void,
fn foo() void {}
fn bar() void {}
};
const x: U = .{ .f = U.foo };
try std.testing.expect(x.f == U.foo);
x.f();
comptime var y: U = .{ .f = U.bar };
try std.testing.expect(y.f == U.bar);
y.f();
y.f = U.foo;
try std.testing.expect(y.f == U.foo);
y.f();
}