Skip to content

Commit 55468a8

Browse files
jacobly0mlugg
authored andcommitted
Sema: fix union layout logic to match struct layout logic
1 parent aadd392 commit 55468a8

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

src/Sema.zig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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`.
3505835058
pub 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

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3915,29 +3915,30 @@ fn resolveUnionInner(
39153915
pub 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
}

0 commit comments

Comments
 (0)