Commit 65a6bf1267

Silver <14016168+silversquirl@users.noreply.github.com>
2025-09-18 06:39:47
fix handling of comptime-only union fields in `Type.getUnionLayout` (#25182)
Fixes #25180
1 parent 220c679
Changed files (2)
src
test
behavior
src/Type.zig
@@ -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);
     }
test/behavior/union.zig
@@ -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();
+}