mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Merge pull request #25186 from ziglang/vector-memory-coercion
frontend: vectors and arrays no longer support in-memory coercion
This commit is contained in:
commit
05cff8a558
9 changed files with 36 additions and 50 deletions
|
|
@ -1969,6 +1969,14 @@ or
|
|||
</p>
|
||||
{#see_also|@splat|@shuffle|@select|@reduce#}
|
||||
|
||||
{#header_open|Relationship with Arrays#}
|
||||
<p>Vectors and {#link|Arrays#} each have a well-defined <strong>bit layout</strong>
|
||||
and therefore support {#link|@bitCast#} between each other. {#link|Type Coercion#} implicitly peforms
|
||||
{#syntax#}@bitCast{#endsyntax#}.</p>
|
||||
<p>Arrays have well-defined byte layout, but vectors do not, making {#link|@ptrCast#} between
|
||||
them {#link|Illegal Behavior#}.</p>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|Destructuring Vectors#}
|
||||
<p>
|
||||
Vectors can be destructured:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ test "Basic vector usage" {
|
|||
}
|
||||
|
||||
test "Conversion between vectors, arrays, and slices" {
|
||||
// Vectors and fixed-length arrays can be automatically assigned back and forth
|
||||
// Vectors can be coerced to arrays, and vice versa.
|
||||
const arr1: [4]f32 = [_]f32{ 1.1, 3.2, 4.5, 5.6 };
|
||||
const vec: @Vector(4, f32) = arr1;
|
||||
const arr2: [4]f32 = vec;
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ pub fn assertReadable(slice: []const volatile u8) void {
|
|||
/// Invokes detectable illegal behavior when the provided array is not aligned
|
||||
/// to the provided amount.
|
||||
pub fn assertAligned(ptr: anytype, comptime alignment: std.mem.Alignment) void {
|
||||
const aligned_ptr: *align(alignment.toByteUnits()) anyopaque = @ptrCast(@alignCast(ptr));
|
||||
const aligned_ptr: *align(alignment.toByteUnits()) const anyopaque = @ptrCast(@alignCast(ptr));
|
||||
_ = aligned_ptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1156,10 +1156,10 @@ pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]co
|
|||
}
|
||||
}
|
||||
|
||||
assert(std.mem.isAligned(@intFromPtr(&p[i]), block_size));
|
||||
std.debug.assertAligned(&p[i], .fromByteUnits(block_size));
|
||||
while (true) {
|
||||
const block: *const Block = @ptrCast(@alignCast(p[i..][0..block_len]));
|
||||
const matches = block.* == mask;
|
||||
const block: Block = p[i..][0..block_len].*;
|
||||
const matches = block == mask;
|
||||
if (@reduce(.Or, matches)) {
|
||||
return i + std.simd.firstTrue(matches).?;
|
||||
}
|
||||
|
|
|
|||
44
src/Sema.zig
44
src/Sema.zig
|
|
@ -29649,50 +29649,6 @@ pub fn coerceInMemoryAllowed(
|
|||
return .ok;
|
||||
}
|
||||
|
||||
// Arrays <-> Vectors
|
||||
if ((dest_tag == .vector and src_tag == .array) or
|
||||
(dest_tag == .array and src_tag == .vector))
|
||||
{
|
||||
const dest_len = dest_ty.arrayLen(zcu);
|
||||
const src_len = src_ty.arrayLen(zcu);
|
||||
if (dest_len != src_len) {
|
||||
return .{ .array_len = .{
|
||||
.actual = src_len,
|
||||
.wanted = dest_len,
|
||||
} };
|
||||
}
|
||||
|
||||
const dest_elem_ty = dest_ty.childType(zcu);
|
||||
const src_elem_ty = src_ty.childType(zcu);
|
||||
const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null);
|
||||
if (child != .ok) {
|
||||
return .{ .array_elem = .{
|
||||
.child = try child.dupe(sema.arena),
|
||||
.actual = src_elem_ty,
|
||||
.wanted = dest_elem_ty,
|
||||
} };
|
||||
}
|
||||
|
||||
if (dest_tag == .array) {
|
||||
const dest_info = dest_ty.arrayInfo(zcu);
|
||||
if (dest_info.sentinel != null) {
|
||||
return .{ .array_sentinel = .{
|
||||
.actual = Value.@"unreachable",
|
||||
.wanted = dest_info.sentinel.?,
|
||||
.ty = dest_info.elem_type,
|
||||
} };
|
||||
}
|
||||
}
|
||||
|
||||
// The memory layout of @Vector(N, iM) is the same as the integer type i(N*M),
|
||||
// that is to say, the padding bits are not in the same place as the array [N]iM.
|
||||
// If there's no padding, the bitcast is possible.
|
||||
const elem_bit_size = dest_elem_ty.bitSize(zcu);
|
||||
const elem_abi_byte_size = dest_elem_ty.abiSize(zcu);
|
||||
if (elem_abi_byte_size * 8 == elem_bit_size)
|
||||
return .ok;
|
||||
}
|
||||
|
||||
// Optionals
|
||||
if (dest_tag == .optional and src_tag == .optional) {
|
||||
if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) {
|
||||
|
|
|
|||
|
|
@ -1737,6 +1737,7 @@ test "peer type resolution: array and vector with same child type" {
|
|||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
var arr: [2]u32 = .{ 0, 1 };
|
||||
var vec: @Vector(2, u32) = .{ 2, 3 };
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ test "basic extern unions" {
|
|||
var foo = FooExtern{ .int = 1 };
|
||||
try expect(foo.int == 1);
|
||||
foo.str.slice = "Well";
|
||||
try expect(std.mem.eql(u8, std.mem.sliceTo(foo.str.slice, 0), "Well"));
|
||||
try expect(foo.str.slice[0] == 'W');
|
||||
try expect(foo.str.slice[1] == 'e');
|
||||
try expect(foo.str.slice[2] == 'l');
|
||||
try expect(foo.str.slice[3] == 'l');
|
||||
try expect(foo.str.slice[4] == 0);
|
||||
}
|
||||
|
||||
const ExternPtrOrInt = extern union {
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ test "array to vector" {
|
|||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
export fn entry() void {
|
||||
_ = foo() catch {};
|
||||
}
|
||||
fn foo() anyerror![4]u32 {
|
||||
return bar();
|
||||
}
|
||||
fn bar() anyerror!@Vector(4, u32) {
|
||||
return .{ 1, 2, 3, 4 };
|
||||
}
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :5:15: error: expected type 'anyerror![4]u32', found 'anyerror!@Vector(4, u32)'
|
||||
// :5:15: note: error union payload '@Vector(4, u32)' cannot cast into error union payload '[4]u32'
|
||||
// :4:18: note: function return type declared here
|
||||
Loading…
Add table
Reference in a new issue