From 0bcf29aff6e4ed536406634f03f7bf61eda1a2b8 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 6 May 2026 10:37:54 +0100 Subject: [PATCH] compiler: correct ABI size of comptime-only optional type Resolves: https://codeberg.org/ziglang/zig/issues/31603 --- src/Type.zig | 19 ++++++++++++------- test/behavior/struct.zig | 13 +++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index 8e8202c023d9d95832f1285839a4654380a23016..4960f60c22520f196e3b3ad3ef31631e33536ddd 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1094,13 +1094,18 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { }, .opt_type => |child_ty_ip| { const child_ty: Type = .fromInterned(child_ty_ip); - if (child_ty.classify(zcu) == .no_possible_value) return 0; - if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu); - // 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 child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?; + switch (child_ty.classify(zcu)) { + .no_possible_value => return 0, // we are OPV + .fully_comptime => return 0, // we are also fully_comptime (same justification as error unions, see below) + .one_possible_value, .partially_comptime, .runtime => { + if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu); + // 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 child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?; + }, + } }, .error_set_type, .inferred_error_set_type => errorAbiSize(zcu), .error_union_type => |error_union| { diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 973eab39c8d3912d36774375af1da268b36ee438..831f994ed0a36d1a295c48341c9c2c6bcda6d4ff 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -2301,3 +2301,16 @@ test "struct queries typeinfo of struct containing pointer back to first struct" }; _ = @as(static.A, undefined); } + +test "pointer to runtime field of struct containing struct containing comptime-only optional" { + const Foo = struct { + padding: struct { a: u8, b: ?comptime_int }, + number: u8, + }; + + const foo: Foo = .{ .padding = undefined, .number = 123 }; + + var ptr: *const u8 = undefined; + ptr = &foo.number; + try expect(ptr.* == 123); +} -- 2.54.0