Commit 2a4e89e0c9

Veikka Tuominen <git@vexu.eu>
2022-09-29 18:02:59
Type: correctly handle ABI align strat for optionals and error unions
Closes #12984
1 parent 3122601
Changed files (3)
src
test
behavior
src/type.zig
@@ -3458,12 +3458,21 @@ pub const Type = extern union {
                     else => {},
                 }
 
+                const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) {
+                    .scalar => |elem_size| elem_size,
+                    .val => switch (strat) {
+                        .sema_kit => unreachable,
+                        .eager => unreachable,
+                        .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
+                    },
+                };
+
                 // Optional types are represented as a struct with the child type as the first
                 // field and a boolean as the second. Since the child type's abi alignment is
                 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
                 // to the child type's ABI alignment.
                 return AbiSizeAdvanced{
-                    .scalar = child_type.abiAlignment(target) + child_type.abiSize(target),
+                    .scalar = child_type.abiAlignment(target) + payload_size,
                 };
             },
 
@@ -3478,7 +3487,14 @@ pub const Type = extern union {
                 }
                 const code_align = abiAlignment(Type.anyerror, target);
                 const payload_align = abiAlignment(data.payload, target);
-                const payload_size = abiSize(data.payload, target);
+                const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) {
+                    .scalar => |elem_size| elem_size,
+                    .val => switch (strat) {
+                        .sema_kit => unreachable,
+                        .eager => unreachable,
+                        .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
+                    },
+                };
 
                 var size: u64 = 0;
                 if (code_align > payload_align) {
test/behavior/bugs/12984.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+pub fn DeleagateWithContext(comptime Function: type) type {
+    const ArgArgs = std.meta.ArgsTuple(Function);
+    return struct {
+        t: ArgArgs,
+    };
+}
+
+pub const OnConfirm = DeleagateWithContext(fn (bool) void);
+pub const CustomDraw = DeleagateWithContext(fn (?OnConfirm) void);
+
+test "simple test" {
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+    var c: CustomDraw = undefined;
+    _ = c;
+}
test/behavior.zig
@@ -98,6 +98,7 @@ test {
     _ = @import("behavior/bugs/12911.zig");
     _ = @import("behavior/bugs/12928.zig");
     _ = @import("behavior/bugs/12945.zig");
+    _ = @import("behavior/bugs/12984.zig");
     _ = @import("behavior/byteswap.zig");
     _ = @import("behavior/byval_arg_var.zig");
     _ = @import("behavior/call.zig");