authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-16 19:40:55-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-16 21:22:57-05:00
loga8ec306b493ddac701f279bfe82808525956f3f2
treee65c5680a640121f8dd211102bf08d3a00c6cf54
parent7266d4497e7879491c4394bb01e3057d75823cea

Sema: fix peer resolution alignment between slice and empty struct

An empty struct that coerces to an empty array should not force `align(1)` on the resulting slice type.

2 files changed, 23 insertions(+), 11 deletions(-)

src/Sema.zig+15-11
......@@ -35010,6 +35010,7 @@ fn resolvePeerTypesInner(
3501035010 // if there were no actual slices. Else, we want the slice index to report a conflict.
3501135011 var opt_slice_idx: ?usize = null;
3501235012
35013 var any_abi_aligned = false;
3501335014 var opt_ptr_info: ?InternPool.Key.PtrType = null;
3501435015 var first_idx: usize = undefined;
3501535016 var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error
......@@ -35054,17 +35055,14 @@ fn resolvePeerTypesInner(
3505435055 } };
3505535056
3505635057 // Note that the align can be always non-zero; Type.ptr will canonicalize it
35057 ptr_info.flags.alignment = Alignment.min(
35058 if (ptr_info.flags.alignment != .none)
35059 ptr_info.flags.alignment
35060 else
35061 try Type.fromInterned(ptr_info.child).abiAlignmentSema(pt),
35062
35063 if (peer_info.flags.alignment != .none)
35064 peer_info.flags.alignment
35065 else
35066 try Type.fromInterned(peer_info.child).abiAlignmentSema(pt),
35067 );
35058 if (peer_info.flags.alignment == .none) {
35059 any_abi_aligned = true;
35060 } else if (ptr_info.flags.alignment == .none) {
35061 any_abi_aligned = true;
35062 ptr_info.flags.alignment = peer_info.flags.alignment;
35063 } else {
35064 ptr_info.flags.alignment = ptr_info.flags.alignment.minStrict(peer_info.flags.alignment);
35065 }
3506835066
3506935067 if (ptr_info.flags.address_space != peer_info.flags.address_space) {
3507035068 return generic_err;
......@@ -35312,6 +35310,12 @@ fn resolvePeerTypesInner(
3531235310 },
3531335311 }
3531435312
35313 if (any_abi_aligned and opt_ptr_info.?.flags.alignment != .none) {
35314 opt_ptr_info.?.flags.alignment = opt_ptr_info.?.flags.alignment.minStrict(
35315 try Type.fromInterned(pointee).abiAlignmentSema(pt),
35316 );
35317 }
35318
3531535319 return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) };
3531635320 },
3531735321
test/behavior/slice.zig+8
......@@ -995,3 +995,11 @@ test "sentinel-terminated 0-length slices" {
995995 try expect(comptime_known_array_value[0] == 2);
996996 try expect(runtime_array_value[0] == 2);
997997}
998
999test "peer slices keep abi alignment with empty struct" {
1000 var cond: bool = undefined;
1001 cond = false;
1002 const slice = if (cond) &[1]u32{42} else &.{};
1003 comptime assert(@TypeOf(slice) == []const u32);
1004 try expect(slice.len == 0);
1005}