diff --git a/doc/langref.html.in b/doc/langref.html.in index cf1c48f9e0..43d350ca2b 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1969,6 +1969,14 @@ or

{#see_also|@splat|@shuffle|@select|@reduce#} + {#header_open|Relationship with Arrays#} +

Vectors and {#link|Arrays#} each have a well-defined bit layout + and therefore support {#link|@bitCast#} between each other. {#link|Type Coercion#} implicitly peforms + {#syntax#}@bitCast{#endsyntax#}.

+

Arrays have well-defined byte layout, but vectors do not, making {#link|@ptrCast#} between + them {#link|Illegal Behavior#}.

+ {#header_close#} + {#header_open|Destructuring Vectors#}

Vectors can be destructured: diff --git a/doc/langref/test_vector.zig b/doc/langref/test_vector.zig index cd1e860886..933a282910 100644 --- a/doc/langref/test_vector.zig +++ b/doc/langref/test_vector.zig @@ -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; diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 18b1568b19..bd849a32d3 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -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; } diff --git a/lib/std/mem.zig b/lib/std/mem.zig index e31e93aae1..8ca34aa51c 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -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).?; } diff --git a/src/Sema.zig b/src/Sema.zig index 587c6b2d70..51b93fb308 100644 --- a/src/Sema.zig +++ b/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)) { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 7eee20e3e0..700bfb0991 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -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 }; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 1807cf14cf..d581d25a1a 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -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 { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 3012830079..4de7c42d49 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -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 { diff --git a/test/cases/compile_errors/in_memory_coerce_vector_to_array.zig b/test/cases/compile_errors/in_memory_coerce_vector_to_array.zig new file mode 100644 index 0000000000..59ecf149dc --- /dev/null +++ b/test/cases/compile_errors/in_memory_coerce_vector_to_array.zig @@ -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