diff --git a/doc/langref.html.in b/doc/langref.html.in index cf1c48f9e03b519c89b77b4d91f3121cf054ca9b..43d350ca2be1952b6b732c32657240978bf60d9c 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 cd1e860886e1cb0bcd9d352fe05241a225322dc3..933a28291001f86f6e11c1077e27c468b3c8ce0c 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 18b1568b19b73c4fff7f003dfa6746e990f9d598..bd849a32d320f0ecb57214bdab7bfb7ecd953bb9 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 e31e93aae15b7d2a357e73aca3679abbbc5a543f..8ca34aa51cf48b2cdb5b76379b3f86ebb9cbab51 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 587c6b2d70f76ab364ddea9424d52efdf82090dc..51b93fb30830576350000e249507a2aad2804e33 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 7eee20e3e01f21b4dc148c73c22e6d73d3170ad3..700bfb09914468e59b5d61cd53e986175affb540 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 1807cf14cf2453b38beef666228881dd4e25b0ad..d581d25a1a6fe2b3558e2d20c3b70b85882146c0 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 3012830079840df4951e1c27f62291f40e5b77fd..4de7c42d49c82ec18686d60322760509c04b97e3 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 0000000000000000000000000000000000000000..59ecf149dc71bc7caa7d597e228c2e1788307e26 --- /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