authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-06 10:37:54+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-05-07 06:21:30+02:00
log0bcf29aff6e4ed536406634f03f7bf61eda1a2b8
treedc83eb5841a9a73e07e72cb1d8c51d377b6f796f
parent45ecd6a99689dbb200342bb576f75a1930455e02

compiler: correct ABI size of comptime-only optional type

Resolves: https://codeberg.org/ziglang/zig/issues/31603

2 files changed, 25 insertions(+), 7 deletions(-)

src/Type.zig+12-7
......@@ -1094,13 +1094,18 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
10941094 },
10951095 .opt_type => |child_ty_ip| {
10961096 const child_ty: Type = .fromInterned(child_ty_ip);
1097 if (child_ty.classify(zcu) == .no_possible_value) return 0;
1098 if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu);
1099 // Optional types are represented as a struct with the child type as the first
1100 // field and a boolean as the second. Since the child type's abi alignment is
1101 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1102 // to the child type's ABI alignment.
1103 return child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?;
1097 switch (child_ty.classify(zcu)) {
1098 .no_possible_value => return 0, // we are OPV
1099 .fully_comptime => return 0, // we are also fully_comptime (same justification as error unions, see below)
1100 .one_possible_value, .partially_comptime, .runtime => {
1101 if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu);
1102 // Optional types are represented as a struct with the child type as the first
1103 // field and a boolean as the second. Since the child type's abi alignment is
1104 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1105 // to the child type's ABI alignment.
1106 return child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?;
1107 },
1108 }
11041109 },
11051110 .error_set_type, .inferred_error_set_type => errorAbiSize(zcu),
11061111 .error_union_type => |error_union| {
test/behavior/struct.zig+13
......@@ -2301,3 +2301,16 @@ test "struct queries typeinfo of struct containing pointer back to first struct"
23012301 };
23022302 _ = @as(static.A, undefined);
23032303}
2304
2305test "pointer to runtime field of struct containing struct containing comptime-only optional" {
2306 const Foo = struct {
2307 padding: struct { a: u8, b: ?comptime_int },
2308 number: u8,
2309 };
2310
2311 const foo: Foo = .{ .padding = undefined, .number = 123 };
2312
2313 var ptr: *const u8 = undefined;
2314 ptr = &foo.number;
2315 try expect(ptr.* == 123);
2316}