Skip to content

Commit 05cff8a

Browse files
authored
Merge pull request ziglang#25186 from ziglang/vector-memory-coercion
frontend: vectors and arrays no longer support in-memory coercion
2 parents 426d65d + 7666d5f commit 05cff8a

File tree

9 files changed

+36
-50
lines changed

9 files changed

+36
-50
lines changed

doc/langref.html.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,6 +1969,14 @@ or
19691969
</p>
19701970
{#see_also|@splat|@shuffle|@select|@reduce#}
19711971

1972+
{#header_open|Relationship with Arrays#}
1973+
<p>Vectors and {#link|Arrays#} each have a well-defined <strong>bit layout</strong>
1974+
and therefore support {#link|@bitCast#} between each other. {#link|Type Coercion#} implicitly peforms
1975+
{#syntax#}@bitCast{#endsyntax#}.</p>
1976+
<p>Arrays have well-defined byte layout, but vectors do not, making {#link|@ptrCast#} between
1977+
them {#link|Illegal Behavior#}.</p>
1978+
{#header_close#}
1979+
19721980
{#header_open|Destructuring Vectors#}
19731981
<p>
19741982
Vectors can be destructured:

doc/langref/test_vector.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test "Basic vector usage" {
1717
}
1818

1919
test "Conversion between vectors, arrays, and slices" {
20-
// Vectors and fixed-length arrays can be automatically assigned back and forth
20+
// Vectors can be coerced to arrays, and vice versa.
2121
const arr1: [4]f32 = [_]f32{ 1.1, 3.2, 4.5, 5.6 };
2222
const vec: @Vector(4, f32) = arr1;
2323
const arr2: [4]f32 = vec;

lib/std/debug.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ pub fn assertReadable(slice: []const volatile u8) void {
569569
/// Invokes detectable illegal behavior when the provided array is not aligned
570570
/// to the provided amount.
571571
pub fn assertAligned(ptr: anytype, comptime alignment: std.mem.Alignment) void {
572-
const aligned_ptr: *align(alignment.toByteUnits()) anyopaque = @ptrCast(@alignCast(ptr));
572+
const aligned_ptr: *align(alignment.toByteUnits()) const anyopaque = @ptrCast(@alignCast(ptr));
573573
_ = aligned_ptr;
574574
}
575575

lib/std/mem.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,10 +1156,10 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co
11561156
}
11571157
}
11581158

1159-
assert(std.mem.isAligned(@intFromPtr(&p[i]), block_size));
1159+
std.debug.assertAligned(&p[i], .fromByteUnits(block_size));
11601160
while (true) {
1161-
const block: *const Block = @ptrCast(@alignCast(p[i..][0..block_len]));
1162-
const matches = block.* == mask;
1161+
const block: Block = p[i..][0..block_len].*;
1162+
const matches = block == mask;
11631163
if (@reduce(.Or, matches)) {
11641164
return i + std.simd.firstTrue(matches).?;
11651165
}

src/Sema.zig

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29649,50 +29649,6 @@ pub fn coerceInMemoryAllowed(
2964929649
return .ok;
2965029650
}
2965129651

29652-
// Arrays <-> Vectors
29653-
if ((dest_tag == .vector and src_tag == .array) or
29654-
(dest_tag == .array and src_tag == .vector))
29655-
{
29656-
const dest_len = dest_ty.arrayLen(zcu);
29657-
const src_len = src_ty.arrayLen(zcu);
29658-
if (dest_len != src_len) {
29659-
return .{ .array_len = .{
29660-
.actual = src_len,
29661-
.wanted = dest_len,
29662-
} };
29663-
}
29664-
29665-
const dest_elem_ty = dest_ty.childType(zcu);
29666-
const src_elem_ty = src_ty.childType(zcu);
29667-
const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null);
29668-
if (child != .ok) {
29669-
return .{ .array_elem = .{
29670-
.child = try child.dupe(sema.arena),
29671-
.actual = src_elem_ty,
29672-
.wanted = dest_elem_ty,
29673-
} };
29674-
}
29675-
29676-
if (dest_tag == .array) {
29677-
const dest_info = dest_ty.arrayInfo(zcu);
29678-
if (dest_info.sentinel != null) {
29679-
return .{ .array_sentinel = .{
29680-
.actual = Value.@"unreachable",
29681-
.wanted = dest_info.sentinel.?,
29682-
.ty = dest_info.elem_type,
29683-
} };
29684-
}
29685-
}
29686-
29687-
// The memory layout of @Vector(N, iM) is the same as the integer type i(N*M),
29688-
// that is to say, the padding bits are not in the same place as the array [N]iM.
29689-
// If there's no padding, the bitcast is possible.
29690-
const elem_bit_size = dest_elem_ty.bitSize(zcu);
29691-
const elem_abi_byte_size = dest_elem_ty.abiSize(zcu);
29692-
if (elem_abi_byte_size * 8 == elem_bit_size)
29693-
return .ok;
29694-
}
29695-
2969629652
// Optionals
2969729653
if (dest_tag == .optional and src_tag == .optional) {
2969829654
if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) {

test/behavior/cast.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,7 @@ test "peer type resolution: array and vector with same child type" {
17371737
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17381738
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17391739
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1740+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
17401741

17411742
var arr: [2]u32 = .{ 0, 1 };
17421743
var vec: @Vector(2, u32) = .{ 2, 3 };

test/behavior/union.zig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@ test "basic extern unions" {
103103
var foo = FooExtern{ .int = 1 };
104104
try expect(foo.int == 1);
105105
foo.str.slice = "Well";
106-
try expect(std.mem.eql(u8, std.mem.sliceTo(foo.str.slice, 0), "Well"));
106+
try expect(foo.str.slice[0] == 'W');
107+
try expect(foo.str.slice[1] == 'e');
108+
try expect(foo.str.slice[2] == 'l');
109+
try expect(foo.str.slice[3] == 'l');
110+
try expect(foo.str.slice[4] == 0);
107111
}
108112

109113
const ExternPtrOrInt = extern union {

test/behavior/vector.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ test "array to vector" {
196196
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
197197
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
198198
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
199+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
199200

200201
const S = struct {
201202
fn doTheTest() !void {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export fn entry() void {
2+
_ = foo() catch {};
3+
}
4+
fn foo() anyerror![4]u32 {
5+
return bar();
6+
}
7+
fn bar() anyerror!@Vector(4, u32) {
8+
return .{ 1, 2, 3, 4 };
9+
}
10+
// error
11+
// backend=stage2
12+
// target=native
13+
//
14+
// :5:15: error: expected type 'anyerror![4]u32', found 'anyerror!@Vector(4, u32)'
15+
// :5:15: note: error union payload '@Vector(4, u32)' cannot cast into error union payload '[4]u32'
16+
// :4:18: note: function return type declared here

0 commit comments

Comments
 (0)