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(...@@ -35010,6 +35010,7 @@ fn resolvePeerTypesInner(
35010 // if there were no actual slices. Else, we want the slice index to report a conflict.35010 // if there were no actual slices. Else, we want the slice index to report a conflict.
35011 var opt_slice_idx: ?usize = null;35011 var opt_slice_idx: ?usize = null;
3501235012
35013 var any_abi_aligned = false;
35013 var opt_ptr_info: ?InternPool.Key.PtrType = null;35014 var opt_ptr_info: ?InternPool.Key.PtrType = null;
35014 var first_idx: usize = undefined;35015 var first_idx: usize = undefined;
35015 var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error35016 var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error
...@@ -35054,17 +35055,14 @@ fn resolvePeerTypesInner(...@@ -35054,17 +35055,14 @@ fn resolvePeerTypesInner(
35054 } };35055 } };
3505535056
35056 // Note that the align can be always non-zero; Type.ptr will canonicalize it35057 // Note that the align can be always non-zero; Type.ptr will canonicalize it
35057 ptr_info.flags.alignment = Alignment.min(35058 if (peer_info.flags.alignment == .none) {
35058 if (ptr_info.flags.alignment != .none)35059 any_abi_aligned = true;
35059 ptr_info.flags.alignment35060 } else if (ptr_info.flags.alignment == .none) {
35060 else35061 any_abi_aligned = true;
35061 try Type.fromInterned(ptr_info.child).abiAlignmentSema(pt),35062 ptr_info.flags.alignment = peer_info.flags.alignment;
3506235063 } else {
35063 if (peer_info.flags.alignment != .none)35064 ptr_info.flags.alignment = ptr_info.flags.alignment.minStrict(peer_info.flags.alignment);
35064 peer_info.flags.alignment35065 }
35065 else
35066 try Type.fromInterned(peer_info.child).abiAlignmentSema(pt),
35067 );
3506835066
35069 if (ptr_info.flags.address_space != peer_info.flags.address_space) {35067 if (ptr_info.flags.address_space != peer_info.flags.address_space) {
35070 return generic_err;35068 return generic_err;
...@@ -35312,6 +35310,12 @@ fn resolvePeerTypesInner(...@@ -35312,6 +35310,12 @@ fn resolvePeerTypesInner(
35312 },35310 },
35313 }35311 }
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
35315 return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) };35319 return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) };
35316 },35320 },
3531735321
test/behavior/slice.zig+8
...@@ -995,3 +995,11 @@ test "sentinel-terminated 0-length slices" {...@@ -995,3 +995,11 @@ test "sentinel-terminated 0-length slices" {
995 try expect(comptime_known_array_value[0] == 2);995 try expect(comptime_known_array_value[0] == 2);
996 try expect(runtime_array_value[0] == 2);996 try expect(runtime_array_value[0] == 2);
997}997}
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}