authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-09 02:34:30-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-12 17:51:30+01:00
log746137034e244d863a022b821ae0a1952d9d93c1
tree62ad6883d960d3f995202eb4901aecddbf0fb957
parentd312dfc1f21a9194dd06c1d45f653bdaf823d2f6
signaturelock-open Commit is signed but in an unrecognized format.

Sema: fix union layout logic to match struct layout logic


2 files changed, 26 insertions(+), 17 deletions(-)

src/Sema.zig+9-1
......@@ -35054,7 +35054,7 @@ pub fn resolveUnionAlignment(
3505435054 union_type.setAlignment(ip, max_align);
3505535055}
3505635056
35057/// This logic must be kept in sync with `Zcu.getUnionLayout`.
35057/// This logic must be kept in sync with `Type.getUnionLayout`.
3505835058pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
3505935059 const pt = sema.pt;
3506035060 const ip = &pt.zcu.intern_pool;
......@@ -35090,6 +35090,14 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
3509035090 const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
3509135091 if (field_ty.isNoReturn(pt.zcu)) continue;
3509235092
35093 // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s,
35094 // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type,
35095 // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us.
35096 // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to
35097 // be queried, enabling failures to be handled with the emission of a compile error, and also in
35098 // `hasRuntimeBits` for ever being able to infinite recurse in the first place.
35099 try field_ty.resolveLayout(pt);
35100
3509335101 if (try field_ty.hasRuntimeBitsSema(pt)) {
3509435102 max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
3509535103 error.AnalysisFail => {
src/Type.zig+17-16
......@@ -3915,29 +3915,30 @@ fn resolveUnionInner(
39153915pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout {
39163916 const ip = &zcu.intern_pool;
39173917 assert(loaded_union.haveLayout(ip));
3918 var most_aligned_field: u32 = undefined;
3919 var most_aligned_field_size: u64 = undefined;
3920 var biggest_field: u32 = undefined;
3918 var most_aligned_field: u32 = 0;
3919 var most_aligned_field_align: InternPool.Alignment = .@"1";
3920 var most_aligned_field_size: u64 = 0;
3921 var biggest_field: u32 = 0;
39213922 var payload_size: u64 = 0;
39223923 var payload_align: InternPool.Alignment = .@"1";
3923 for (loaded_union.field_types.get(ip), 0..) |field_ty, field_index| {
3924 if (Type.fromInterned(field_ty).isNoReturn(zcu)) continue;
3924 for (loaded_union.field_types.get(ip), 0..) |field_ty_ip_index, field_index| {
3925 const field_ty: Type = .fromInterned(field_ty_ip_index);
3926 if (field_ty.isNoReturn(zcu)) continue;
39253927
39263928 const explicit_align = loaded_union.fieldAlign(ip, field_index);
39273929 const field_align = if (explicit_align != .none)
39283930 explicit_align
39293931 else
3930 Type.fromInterned(field_ty).abiAlignment(zcu);
3931 if (Type.fromInterned(field_ty).hasRuntimeBits(zcu)) {
3932 const field_size = Type.fromInterned(field_ty).abiSize(zcu);
3933 if (field_size > payload_size) {
3934 payload_size = field_size;
3935 biggest_field = @intCast(field_index);
3936 }
3937 if (field_align.compare(.gte, payload_align)) {
3938 most_aligned_field = @intCast(field_index);
3939 most_aligned_field_size = field_size;
3940 }
3932 field_ty.abiAlignment(zcu);
3933 const field_size = field_ty.abiSize(zcu);
3934 if (field_size > payload_size) {
3935 payload_size = field_size;
3936 biggest_field = @intCast(field_index);
3937 }
3938 if (field_size > 0 and field_align.compare(.gte, most_aligned_field_align)) {
3939 most_aligned_field = @intCast(field_index);
3940 most_aligned_field_align = field_align;
3941 most_aligned_field_size = field_size;
39413942 }
39423943 payload_align = payload_align.max(field_align);
39433944 }