Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion doc/langref/test_vector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/std/debug.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/std/mem.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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).?;
}
Expand Down
44 changes: 0 additions & 44 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
1 change: 1 addition & 0 deletions test/behavior/cast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
6 changes: 5 additions & 1 deletion test/behavior/union.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions test/behavior/vector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
16 changes: 16 additions & 0 deletions test/cases/compile_errors/in_memory_coerce_vector_to_array.zig
Original file line number Diff line number Diff line change
@@ -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