Commit ba6abd71c2

mlugg <mlugg@mlugg.co.uk>
2025-08-13 00:18:05
llvm: unions which are equivalent to enums are not by-ref
The LLVM backend lowers unions where all fields are zero-bit as equivalent to their backing enum, and expects them to have the same by-ref-ness in at least one place in the backend, probably more. Resolves: #23577
1 parent 38ba425
Changed files (2)
src
codegen
test
behavior
src/codegen/llvm.zig
@@ -12777,7 +12777,7 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {
         },
         .@"union" => switch (ty.containerLayout(zcu)) {
             .@"packed" => return false,
-            else => return ty.hasRuntimeBits(zcu),
+            else => return ty.hasRuntimeBits(zcu) and !ty.unionHasAllZeroBitFieldTypes(zcu),
         },
         .error_union => {
             const payload_ty = ty.errorUnionPayload(zcu);
test/behavior/cast.zig
@@ -2722,3 +2722,18 @@ test "@intFromFloat vector boundary cases" {
     try S.doTheTest();
     try comptime S.doTheTest();
 }
+
+test "coerce enum to union with zero-bit fields through local variables" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+
+    const E = enum(u1) { foo, bar };
+    const U = union(E) { foo, bar };
+
+    var runtime: E = undefined;
+    runtime = .foo;
+
+    var result: U = undefined;
+    result = runtime;
+
+    try expect(result == .foo);
+}