2019-08-19 14:46:12 -04:00
|
|
|
const std = @import("std");
|
2021-10-12 21:26:59 -07:00
|
|
|
const builtin = @import("builtin");
|
2020-03-03 12:13:13 +01:00
|
|
|
const testing = std.testing;
|
2019-08-19 14:46:12 -04:00
|
|
|
const mem = std.mem;
|
2024-01-15 16:01:13 +11:00
|
|
|
const assert = std.debug.assert;
|
2020-03-03 12:13:13 +01:00
|
|
|
const expect = testing.expect;
|
|
|
|
|
const expectEqual = testing.expectEqual;
|
2021-09-13 21:37:11 -07:00
|
|
|
|
2022-01-17 20:30:44 +01:00
|
|
|
test "array to slice" {
|
|
|
|
|
const a: u32 align(4) = 3;
|
|
|
|
|
const b: u32 align(8) = 4;
|
|
|
|
|
const a_slice: []align(1) const u32 = @as(*const [1]u32, &a)[0..];
|
|
|
|
|
const b_slice: []align(1) const u32 = @as(*const [1]u32, &b)[0..];
|
|
|
|
|
try expect(a_slice[0] + b_slice[0] == 7);
|
|
|
|
|
|
|
|
|
|
const d: []const u32 = &[2]u32{ 1, 2 };
|
|
|
|
|
const e: []const u32 = &[3]u32{ 3, 4, 5 };
|
|
|
|
|
try expect(d[0] + e[0] + d[1] + e[1] == 10);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 21:37:11 -07:00
|
|
|
test "arrays" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-01-18 21:41:33 +01:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-09-13 21:37:11 -07:00
|
|
|
var array: [5]u32 = undefined;
|
|
|
|
|
|
|
|
|
|
var i: u32 = 0;
|
|
|
|
|
while (i < 5) {
|
|
|
|
|
array[i] = i + 1;
|
|
|
|
|
i = array[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
var accumulator = @as(u32, 0);
|
|
|
|
|
while (i < 5) {
|
|
|
|
|
accumulator += array[i];
|
|
|
|
|
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try expect(accumulator == 15);
|
|
|
|
|
try expect(getArrayLen(&array) == 5);
|
|
|
|
|
}
|
|
|
|
|
fn getArrayLen(a: []const u32) usize {
|
|
|
|
|
return a.len;
|
|
|
|
|
}
|
2021-09-30 18:31:27 -04:00
|
|
|
|
2022-12-24 02:33:06 -05:00
|
|
|
test "array concat with undefined" {
|
2022-12-24 02:54:06 -05:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2023-01-04 10:46:05 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-12-24 02:54:06 -05:00
|
|
|
|
Sema: allow comptime mutation of multiple array elements
Previously, if you had a pointer to multiple array elements and tried to
write to it at comptime, it was incorrectly treated as a pointer to one
specific array value, leading to an assertion down the line. If we try
to mutate a value at an elem_ptr larger than the element type, we need
to perform a modification to multiple array elements.
This solution isn't ideal, since it will result in storePtrVal
serializing the whole array, modifying the relevant parts, and storing
it back. Ideally, it would only take the required elements. However,
this change would have been more complex, and this is a fairly rare
operation (nobody ever ran into the bug before after all), so it doesn't
matter all that much.
2023-03-03 21:13:31 +00:00
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
{
|
|
|
|
|
var array = "hello".* ++ @as([5]u8, undefined);
|
|
|
|
|
array[5..10].* = "world".*;
|
|
|
|
|
try std.testing.expect(std.mem.eql(u8, &array, "helloworld"));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var array = @as([5]u8, undefined) ++ "world".*;
|
|
|
|
|
array[0..5].* = "hello".*;
|
|
|
|
|
try std.testing.expect(std.mem.eql(u8, &array, "helloworld"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-12-24 02:33:06 -05:00
|
|
|
}
|
|
|
|
|
|
2022-12-24 02:32:13 -05:00
|
|
|
test "array concat with tuple" {
|
2022-12-27 14:44:04 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-12-24 02:54:06 -05:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2023-01-04 10:46:05 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-12-24 02:54:06 -05:00
|
|
|
|
2022-12-24 02:32:13 -05:00
|
|
|
const array: [2]u8 = .{ 1, 2 };
|
|
|
|
|
{
|
|
|
|
|
const seq = array ++ .{ 3, 4 };
|
|
|
|
|
try std.testing.expectEqualSlices(u8, &.{ 1, 2, 3, 4 }, &seq);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
const seq = .{ 3, 4 } ++ array;
|
|
|
|
|
try std.testing.expectEqualSlices(u8, &.{ 3, 4, 1, 2 }, &seq);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array init with concat" {
|
2023-03-12 00:24:19 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2023-05-11 09:23:34 +03:30
|
|
|
|
2022-12-24 02:32:13 -05:00
|
|
|
const a = 'a';
|
|
|
|
|
var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };
|
|
|
|
|
try expect(std.mem.eql(u8, &i, "abcd"));
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-30 18:31:27 -04:00
|
|
|
test "array init with mult" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-09-30 18:31:27 -04:00
|
|
|
const a = 'a';
|
|
|
|
|
var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
|
|
|
|
|
try expect(std.mem.eql(u8, &i, "abababab"));
|
2021-09-30 21:31:46 -04:00
|
|
|
|
|
|
|
|
var j: [4]u8 = [1]u8{'a'} ** 4;
|
|
|
|
|
try expect(std.mem.eql(u8, &j, "aaaa"));
|
2021-09-30 18:31:27 -04:00
|
|
|
}
|
2021-10-07 15:27:05 -07:00
|
|
|
|
|
|
|
|
test "array literal with explicit type" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2023-01-04 10:46:05 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-10-07 15:27:05 -07:00
|
|
|
const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };
|
|
|
|
|
|
|
|
|
|
try expect(hex_mult.len == 4);
|
|
|
|
|
try expect(hex_mult[1] == 256);
|
|
|
|
|
}
|
2021-10-07 16:01:13 -07:00
|
|
|
|
|
|
|
|
test "array literal with inferred length" {
|
|
|
|
|
const hex_mult = [_]u16{ 4096, 256, 16, 1 };
|
|
|
|
|
|
|
|
|
|
try expect(hex_mult.len == 4);
|
|
|
|
|
try expect(hex_mult[1] == 256);
|
|
|
|
|
}
|
2021-10-11 11:00:32 -07:00
|
|
|
|
|
|
|
|
test "array dot len const expr" {
|
|
|
|
|
try expect(comptime x: {
|
|
|
|
|
break :x some_array.len == 4;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ArrayDotLenConstExpr = struct {
|
|
|
|
|
y: [some_array.len]u8,
|
|
|
|
|
};
|
|
|
|
|
const some_array = [_]u8{ 0, 1, 2, 3 };
|
|
|
|
|
|
|
|
|
|
test "array literal with specified size" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-17 17:54:37 +01:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-10-11 11:00:32 -07:00
|
|
|
var array = [2]u8{ 1, 2 };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &array;
|
2021-10-11 11:00:32 -07:00
|
|
|
try expect(array[0] == 1);
|
|
|
|
|
try expect(array[1] == 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array len field" {
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
|
|
2021-10-11 11:00:32 -07:00
|
|
|
var arr = [4]u8{ 0, 0, 0, 0 };
|
2023-11-16 13:21:18 +00:00
|
|
|
const ptr = &arr;
|
2021-10-11 11:00:32 -07:00
|
|
|
try expect(arr.len == 4);
|
2024-01-15 16:01:13 +11:00
|
|
|
comptime assert(arr.len == 4);
|
2021-10-11 11:00:32 -07:00
|
|
|
try expect(ptr.len == 4);
|
2024-01-15 16:01:13 +11:00
|
|
|
comptime assert(ptr.len == 4);
|
2022-03-11 09:36:57 -08:00
|
|
|
try expect(@TypeOf(arr.len) == usize);
|
2021-10-11 11:00:32 -07:00
|
|
|
}
|
2021-10-12 21:26:59 -07:00
|
|
|
|
|
|
|
|
test "array with sentinels" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-10-12 21:26:59 -07:00
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest(is_ct: bool) !void {
|
2022-03-02 17:28:39 -07:00
|
|
|
{
|
2021-10-12 21:26:59 -07:00
|
|
|
var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
|
|
|
|
|
try expect(zero_sized[0] == 0xde);
|
2023-11-16 13:21:18 +00:00
|
|
|
var reinterpreted: *[1]u8 = @ptrCast(&zero_sized);
|
|
|
|
|
_ = &reinterpreted;
|
2021-10-12 21:26:59 -07:00
|
|
|
try expect(reinterpreted[0] == 0xde);
|
|
|
|
|
}
|
|
|
|
|
var arr: [3:0x55]u8 = undefined;
|
|
|
|
|
// Make sure the sentinel pointer is pointing after the last element.
|
|
|
|
|
if (!is_ct) {
|
2023-06-15 13:14:16 +06:00
|
|
|
const sentinel_ptr = @intFromPtr(&arr[3]);
|
|
|
|
|
const last_elem_ptr = @intFromPtr(&arr[2]);
|
2021-10-12 21:26:59 -07:00
|
|
|
try expect((sentinel_ptr - last_elem_ptr) == 1);
|
|
|
|
|
}
|
|
|
|
|
// Make sure the sentinel is writeable.
|
|
|
|
|
arr[3] = 0x55;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try S.doTheTest(false);
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest(true);
|
2021-10-12 21:26:59 -07:00
|
|
|
}
|
2021-10-13 21:20:38 -07:00
|
|
|
|
|
|
|
|
test "void arrays" {
|
|
|
|
|
var array: [4]void = undefined;
|
|
|
|
|
array[0] = void{};
|
|
|
|
|
array[1] = array[2];
|
|
|
|
|
try expect(@sizeOf(@TypeOf(array)) == 0);
|
|
|
|
|
try expect(array.len == 4);
|
|
|
|
|
}
|
2021-10-21 19:05:26 -07:00
|
|
|
|
2022-04-01 00:28:46 -07:00
|
|
|
test "nested arrays of strings" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-17 18:10:02 +01:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-10-21 19:05:26 -07:00
|
|
|
const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
|
2023-02-17 20:23:33 -07:00
|
|
|
for (array_of_strings, 0..) |s, i| {
|
2021-10-21 19:05:26 -07:00
|
|
|
if (i == 0) try expect(mem.eql(u8, s, "hello"));
|
|
|
|
|
if (i == 1) try expect(mem.eql(u8, s, "this"));
|
|
|
|
|
if (i == 2) try expect(mem.eql(u8, s, "is"));
|
|
|
|
|
if (i == 3) try expect(mem.eql(u8, s, "my"));
|
|
|
|
|
if (i == 4) try expect(mem.eql(u8, s, "thing"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-01 00:28:46 -07:00
|
|
|
test "nested arrays of integers" {
|
2022-04-22 07:52:21 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2023-01-04 10:46:05 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-04-01 00:28:46 -07:00
|
|
|
|
|
|
|
|
const array_of_numbers = [_][2]u8{
|
|
|
|
|
[2]u8{ 1, 2 },
|
|
|
|
|
[2]u8{ 3, 4 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try expect(array_of_numbers[0][0] == 1);
|
|
|
|
|
try expect(array_of_numbers[0][1] == 2);
|
|
|
|
|
try expect(array_of_numbers[1][0] == 3);
|
|
|
|
|
try expect(array_of_numbers[1][1] == 4);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 19:05:26 -07:00
|
|
|
test "implicit comptime in array type size" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-10-21 19:05:26 -07:00
|
|
|
var arr: [plusOne(10)]bool = undefined;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &arr;
|
2021-10-21 19:05:26 -07:00
|
|
|
try expect(arr.len == 11);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn plusOne(x: u32) u32 {
|
|
|
|
|
return x + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-27 22:04:21 -07:00
|
|
|
test "single-item pointer to array indexing and slicing" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-12-27 22:04:21 -07:00
|
|
|
try testSingleItemPtrArrayIndexSlice();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime testSingleItemPtrArrayIndexSlice();
|
2021-12-27 22:04:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn testSingleItemPtrArrayIndexSlice() !void {
|
|
|
|
|
{
|
|
|
|
|
var array: [4]u8 = "aaaa".*;
|
|
|
|
|
doSomeMangling(&array);
|
|
|
|
|
try expect(mem.eql(u8, "azya", &array));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var array = "aaaa".*;
|
|
|
|
|
doSomeMangling(&array);
|
|
|
|
|
try expect(mem.eql(u8, "azya", &array));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn doSomeMangling(array: *[4]u8) void {
|
|
|
|
|
array[1] = 'z';
|
|
|
|
|
array[2..3][0] = 'y';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "implicit cast zero sized array ptr to slice" {
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
|
2021-12-27 22:04:21 -07:00
|
|
|
{
|
|
|
|
|
var b = "".*;
|
|
|
|
|
const c: []const u8 = &b;
|
|
|
|
|
try expect(c.len == 0);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var b: [0]u8 = "".*;
|
|
|
|
|
const c: []const u8 = &b;
|
|
|
|
|
try expect(c.len == 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "anonymous list literal syntax" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-17 17:54:37 +01:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-01-17 20:30:44 +01:00
|
|
|
|
2021-12-27 22:04:21 -07:00
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var array: [4]u8 = .{ 1, 2, 3, 4 };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &array;
|
2021-12-27 22:04:21 -07:00
|
|
|
try expect(array[0] == 1);
|
|
|
|
|
try expect(array[1] == 2);
|
|
|
|
|
try expect(array[2] == 3);
|
|
|
|
|
try expect(array[3] == 4);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2021-12-27 22:04:21 -07:00
|
|
|
}
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
var s_array: [8]Sub = undefined;
|
|
|
|
|
const Sub = struct { b: u8 };
|
|
|
|
|
const Str = struct { a: []Sub };
|
|
|
|
|
test "set global var array via slice embedded in struct" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
var s = Str{ .a = s_array[0..] };
|
|
|
|
|
|
|
|
|
|
s.a[0].b = 1;
|
|
|
|
|
s.a[1].b = 2;
|
|
|
|
|
s.a[2].b = 3;
|
|
|
|
|
|
|
|
|
|
try expect(s_array[0].b == 1);
|
|
|
|
|
try expect(s_array[1].b == 2);
|
|
|
|
|
try expect(s_array[2].b == 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "read/write through global variable array of struct fields initialized via array mult" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
try expect(storage[0].term == 1);
|
|
|
|
|
storage[0] = MyStruct{ .term = 123 };
|
|
|
|
|
try expect(storage[0].term == 123);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub const MyStruct = struct {
|
|
|
|
|
term: usize,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var storage: [1]MyStruct = [_]MyStruct{MyStruct{ .term = 1 }} ** 1;
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "implicit cast single-item pointer" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
try testImplicitCastSingleItemPtr();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime testImplicitCastSingleItemPtr();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn testImplicitCastSingleItemPtr() !void {
|
|
|
|
|
var byte: u8 = 100;
|
|
|
|
|
const slice = @as(*[1]u8, &byte)[0..];
|
|
|
|
|
slice[0] += 1;
|
|
|
|
|
try expect(byte == 101);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn testArrayByValAtComptime(b: [2]u8) u8 {
|
|
|
|
|
return b[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "comptime evaluating function that takes array by value" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const arr = [_]u8{ 1, 2 };
|
|
|
|
|
const x = comptime testArrayByValAtComptime(arr);
|
|
|
|
|
const y = comptime testArrayByValAtComptime(arr);
|
|
|
|
|
try expect(x == 1);
|
|
|
|
|
try expect(y == 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "runtime initialize array elem and then implicit cast to slice" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
var two: i32 = 2;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &two;
|
2022-02-12 21:13:07 -07:00
|
|
|
const x: []const i32 = &[_]i32{two};
|
|
|
|
|
try expect(x[0] == 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array literal as argument to function" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn entry(two: i32) !void {
|
|
|
|
|
try foo(&[_]i32{ 1, 2, 3 });
|
|
|
|
|
try foo(&[_]i32{ 1, two, 3 });
|
|
|
|
|
try foo2(true, &[_]i32{ 1, 2, 3 });
|
|
|
|
|
try foo2(true, &[_]i32{ 1, two, 3 });
|
|
|
|
|
}
|
|
|
|
|
fn foo(x: []const i32) !void {
|
|
|
|
|
try expect(x[0] == 1);
|
|
|
|
|
try expect(x[1] == 2);
|
|
|
|
|
try expect(x[2] == 3);
|
|
|
|
|
}
|
|
|
|
|
fn foo2(trash: bool, x: []const i32) !void {
|
|
|
|
|
try expect(trash);
|
|
|
|
|
try expect(x[0] == 1);
|
|
|
|
|
try expect(x[1] == 2);
|
|
|
|
|
try expect(x[2] == 3);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.entry(2);
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.entry(2);
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "double nested array to const slice cast in array literal" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn entry(two: i32) !void {
|
|
|
|
|
const cases = [_][]const []const i32{
|
|
|
|
|
&[_][]const i32{&[_]i32{1}},
|
|
|
|
|
&[_][]const i32{&[_]i32{ 2, 3 }},
|
|
|
|
|
&[_][]const i32{
|
|
|
|
|
&[_]i32{4},
|
|
|
|
|
&[_]i32{ 5, 6, 7 },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
try check(&cases);
|
|
|
|
|
|
|
|
|
|
const cases2 = [_][]const i32{
|
|
|
|
|
&[_]i32{1},
|
|
|
|
|
&[_]i32{ two, 3 },
|
|
|
|
|
};
|
|
|
|
|
try expect(cases2.len == 2);
|
|
|
|
|
try expect(cases2[0].len == 1);
|
|
|
|
|
try expect(cases2[0][0] == 1);
|
|
|
|
|
try expect(cases2[1].len == 2);
|
|
|
|
|
try expect(cases2[1][0] == 2);
|
|
|
|
|
try expect(cases2[1][1] == 3);
|
|
|
|
|
|
|
|
|
|
const cases3 = [_][]const []const i32{
|
|
|
|
|
&[_][]const i32{&[_]i32{1}},
|
|
|
|
|
&[_][]const i32{&[_]i32{ two, 3 }},
|
|
|
|
|
&[_][]const i32{
|
|
|
|
|
&[_]i32{4},
|
|
|
|
|
&[_]i32{ 5, 6, 7 },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
try check(&cases3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check(cases: []const []const []const i32) !void {
|
|
|
|
|
try expect(cases.len == 3);
|
|
|
|
|
try expect(cases[0].len == 1);
|
|
|
|
|
try expect(cases[0][0].len == 1);
|
|
|
|
|
try expect(cases[0][0][0] == 1);
|
|
|
|
|
try expect(cases[1].len == 1);
|
|
|
|
|
try expect(cases[1][0].len == 2);
|
|
|
|
|
try expect(cases[1][0][0] == 2);
|
|
|
|
|
try expect(cases[1][0][1] == 3);
|
|
|
|
|
try expect(cases[2].len == 2);
|
|
|
|
|
try expect(cases[2][0].len == 1);
|
|
|
|
|
try expect(cases[2][0][0] == 4);
|
|
|
|
|
try expect(cases[2][1].len == 3);
|
|
|
|
|
try expect(cases[2][1][0] == 5);
|
|
|
|
|
try expect(cases[2][1][1] == 6);
|
|
|
|
|
try expect(cases[2][1][2] == 7);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.entry(2);
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.entry(2);
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "anonymous literal in array" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
const Foo = struct {
|
|
|
|
|
a: usize = 2,
|
|
|
|
|
b: usize = 4,
|
|
|
|
|
};
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var array: [2]Foo = .{
|
|
|
|
|
.{ .a = 3 },
|
|
|
|
|
.{ .b = 3 },
|
|
|
|
|
};
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &array;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(array[0].a == 3);
|
|
|
|
|
try expect(array[0].b == 4);
|
|
|
|
|
try expect(array[1].a == 2);
|
|
|
|
|
try expect(array[1].b == 3);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "access the null element of a null terminated array" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &array;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(array[4] == 0);
|
|
|
|
|
var len: usize = 4;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &len;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(array[len] == 0);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "type deduction for array subscript expression" {
|
2022-02-14 22:33:01 +01:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var array = [_]u8{ 0x55, 0xAA };
|
|
|
|
|
var v0 = true;
|
|
|
|
|
try expect(@as(u8, 0xAA) == array[if (v0) 1 else 0]);
|
|
|
|
|
var v1 = false;
|
|
|
|
|
try expect(@as(u8, 0x55) == array[if (v1) 1 else 0]);
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &array, &v0, &v1 };
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "sentinel element count towards the ABI size calculation" {
|
2022-02-23 23:27:49 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn doTheTest() !void {
|
2022-02-23 23:27:49 -07:00
|
|
|
const T = extern struct {
|
2022-02-12 21:13:07 -07:00
|
|
|
fill_pre: u8 = 0x55,
|
|
|
|
|
data: [0:0]u8 = undefined,
|
|
|
|
|
fill_post: u8 = 0xAA,
|
|
|
|
|
};
|
|
|
|
|
var x = T{};
|
2023-11-16 13:21:18 +00:00
|
|
|
const as_slice = mem.asBytes(&x);
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(@as(usize, 3) == as_slice.len);
|
|
|
|
|
try expect(@as(u8, 0x55) == as_slice[0]);
|
|
|
|
|
try expect(@as(u8, 0xAA) == as_slice[2]);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "zero-sized array with recursive type definition" {
|
2022-02-23 23:27:49 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2023-05-11 09:23:34 +03:30
|
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const U = struct {
|
|
|
|
|
fn foo(comptime T: type, comptime n: usize) type {
|
|
|
|
|
return struct {
|
|
|
|
|
s: [n]T,
|
|
|
|
|
x: usize = n,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
list: U.foo(@This(), 0),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var t: S = .{ .list = .{ .s = undefined } };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &t;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(@as(usize, 0) == t.list.x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "type coercion of anon struct literal to array" {
|
2022-02-23 23:27:49 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-06-16 01:31:49 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
const U = union {
|
|
|
|
|
a: u32,
|
|
|
|
|
b: bool,
|
|
|
|
|
c: []const u8,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var x1: u8 = 42;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &x1;
|
2022-02-12 21:13:07 -07:00
|
|
|
const t1 = .{ x1, 56, 54 };
|
2023-11-16 13:21:18 +00:00
|
|
|
const arr1: [3]u8 = t1;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(arr1[0] == 42);
|
|
|
|
|
try expect(arr1[1] == 56);
|
|
|
|
|
try expect(arr1[2] == 54);
|
|
|
|
|
|
|
|
|
|
var x2: U = .{ .a = 42 };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &x2;
|
2022-02-12 21:13:07 -07:00
|
|
|
const t2 = .{ x2, .{ .b = true }, .{ .c = "hello" } };
|
2023-11-16 13:21:18 +00:00
|
|
|
const arr2: [3]U = t2;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(arr2[0].a == 42);
|
|
|
|
|
try expect(arr2[1].b == true);
|
|
|
|
|
try expect(mem.eql(u8, arr2[2].c, "hello"));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "type coercion of pointer to anon struct literal to pointer to array" {
|
2022-03-09 18:47:42 -07:00
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
2022-02-12 21:13:07 -07:00
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-02-12 21:13:07 -07:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
const U = union {
|
|
|
|
|
a: u32,
|
|
|
|
|
b: bool,
|
|
|
|
|
c: []const u8,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fn doTheTest() !void {
|
|
|
|
|
var x1: u8 = 42;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &x1;
|
2022-02-12 21:13:07 -07:00
|
|
|
const t1 = &.{ x1, 56, 54 };
|
2023-11-16 13:21:18 +00:00
|
|
|
const arr1: *const [3]u8 = t1;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(arr1[0] == 42);
|
|
|
|
|
try expect(arr1[1] == 56);
|
|
|
|
|
try expect(arr1[2] == 54);
|
|
|
|
|
|
|
|
|
|
var x2: U = .{ .a = 42 };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &x2;
|
2022-02-12 21:13:07 -07:00
|
|
|
const t2 = &.{ x2, .{ .b = true }, .{ .c = "hello" } };
|
2023-11-16 13:21:18 +00:00
|
|
|
const arr2: *const [3]U = t2;
|
2022-02-12 21:13:07 -07:00
|
|
|
try expect(arr2[0].a == 42);
|
|
|
|
|
try expect(arr2[1].b == true);
|
|
|
|
|
try expect(mem.eql(u8, arr2[2].c, "hello"));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try S.doTheTest();
|
2023-06-05 14:29:28 +06:00
|
|
|
try comptime S.doTheTest();
|
2022-02-12 21:13:07 -07:00
|
|
|
}
|
2022-06-03 16:10:18 +03:00
|
|
|
|
2022-10-03 19:52:39 +02:00
|
|
|
test "array with comptime-only element type" {
|
2022-07-14 18:10:54 -07:00
|
|
|
const a = [_]type{ u32, i32 };
|
2022-06-03 16:10:18 +03:00
|
|
|
try testing.expect(a[0] == u32);
|
|
|
|
|
try testing.expect(a[1] == i32);
|
|
|
|
|
}
|
2022-06-15 18:00:29 +03:00
|
|
|
|
|
|
|
|
test "tuple to array handles sentinel" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2022-06-15 18:00:29 +03:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
const a = .{ 1, 2, 3 };
|
|
|
|
|
var b: [3:0]u8 = a;
|
|
|
|
|
};
|
|
|
|
|
try expect(S.b[0] == 1);
|
|
|
|
|
}
|
2022-11-04 17:47:53 +02:00
|
|
|
|
|
|
|
|
test "array init of container level array variable" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2022-10-11 20:39:47 +07:00
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2022-11-04 17:47:53 +02:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
var pair: [2]usize = .{ 1, 2 };
|
|
|
|
|
noinline fn foo(x: usize, y: usize) void {
|
|
|
|
|
pair = [2]usize{ x, y };
|
|
|
|
|
}
|
|
|
|
|
noinline fn bar(x: usize, y: usize) void {
|
|
|
|
|
var tmp: [2]usize = .{ x, y };
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &tmp;
|
2022-11-04 17:47:53 +02:00
|
|
|
pair = tmp;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
try expectEqual([2]usize{ 1, 2 }, S.pair);
|
|
|
|
|
S.foo(3, 4);
|
|
|
|
|
try expectEqual([2]usize{ 3, 4 }, S.pair);
|
|
|
|
|
S.bar(5, 6);
|
|
|
|
|
try expectEqual([2]usize{ 5, 6 }, S.pair);
|
|
|
|
|
}
|
2022-12-31 14:28:21 +02:00
|
|
|
|
|
|
|
|
test "runtime initialized sentinel-terminated array literal" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2022-12-31 14:28:21 +02:00
|
|
|
var c: u16 = 300;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = &c;
|
2022-12-31 14:28:21 +02:00
|
|
|
const f = &[_:0x9999]u16{c};
|
2023-06-22 18:46:56 +01:00
|
|
|
const g = @as(*const [4]u8, @ptrCast(f));
|
2022-12-31 14:28:21 +02:00
|
|
|
try std.testing.expect(g[2] == 0x99);
|
|
|
|
|
try std.testing.expect(g[3] == 0x99);
|
|
|
|
|
}
|
2023-03-19 12:56:37 +00:00
|
|
|
|
|
|
|
|
test "array of array agregate init" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2023-03-19 12:56:37 +00:00
|
|
|
|
|
|
|
|
var a = [1]u32{11} ** 10;
|
|
|
|
|
var b = [1][10]u32{a} ** 2;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &a, &b };
|
2023-03-19 12:56:37 +00:00
|
|
|
try std.testing.expect(b[1][1] == 11);
|
|
|
|
|
}
|
2023-04-20 00:55:52 +01:00
|
|
|
|
|
|
|
|
test "pointer to array has ptr field" {
|
|
|
|
|
const arr: *const [5]u32 = &.{ 10, 20, 30, 40, 50 };
|
|
|
|
|
try std.testing.expect(arr.ptr == @as([*]const u32, arr));
|
|
|
|
|
try std.testing.expect(arr.ptr[0] == 10);
|
|
|
|
|
try std.testing.expect(arr.ptr[1] == 20);
|
|
|
|
|
try std.testing.expect(arr.ptr[2] == 30);
|
|
|
|
|
try std.testing.expect(arr.ptr[3] == 40);
|
2024-03-19 16:14:49 +02:00
|
|
|
try std.testing.expect((&arr.ptr).*[4] == 50);
|
2023-04-20 00:55:52 +01:00
|
|
|
}
|
2023-06-26 20:41:42 +01:00
|
|
|
|
|
|
|
|
test "discarded array init preserves result location" {
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn f(p: *u32) u16 {
|
|
|
|
|
p.* += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var x: u32 = 0;
|
|
|
|
|
_ = [2]u8{
|
|
|
|
|
@intCast(S.f(&x)),
|
|
|
|
|
@intCast(S.f(&x)),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Ensure function was run
|
|
|
|
|
try expect(x == 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array init with no result location has result type" {
|
|
|
|
|
const x = .{ .foo = [2]u16{
|
|
|
|
|
@intCast(10),
|
|
|
|
|
@intCast(20),
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
try expect(x.foo.len == 2);
|
|
|
|
|
try expect(x.foo[0] == 10);
|
|
|
|
|
try expect(x.foo[1] == 20);
|
|
|
|
|
}
|
2023-06-27 19:22:47 -04:00
|
|
|
|
|
|
|
|
test "slicing array of zero-sized values" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2023-06-27 19:22:47 -04:00
|
|
|
|
|
|
|
|
var arr: [32]u0 = undefined;
|
|
|
|
|
for (arr[0..]) |*zero|
|
|
|
|
|
zero.* = 0;
|
|
|
|
|
for (arr[0..]) |zero|
|
|
|
|
|
try expect(zero == 0);
|
|
|
|
|
}
|
AstGen: handle `ty` result location for struct and array init correctly
Well, this was a journey!
The original issue I was trying to fix is covered by the new behavior
test in array.zig: in essence, `ty` and `coerced_ty` result locations
were not correctly propagated.
While fixing this, I noticed a similar bug in struct inits: the type was
propagated to *fields* fine, but the actual struct init was
unnecessarily anonymous, which could lead to unnecessary copies. Note
that the behavior test added in struct.zig was already passing - the bug
here didn't change any easy-to-test behavior - but I figured I'd add it
anyway.
This is a little harder than it seems, because the result type may not
itself be an array/struct type: it could be an optional / error union
wrapper. A new ZIR instruction is introduced to unwrap these.
This is also made a little tricky by the fact that it's possible for
result types to be unknown at the time of semantic analysis (due to
`anytype` parameters), leading to generic poison. In these cases, we
must essentially downgrade to an anonymous initialization.
Fixing these issues exposed *another* bug, related to type resolution in
Sema. That issue is now tracked by #16603. As a temporary workaround for
this bug, a few result locations for builtin function operands have been
disabled in AstGen. This is technically a breaking change, but it's very
minor: I doubt it'll cause any breakage in the wild.
2023-07-29 06:03:51 +01:00
|
|
|
|
|
|
|
|
test "array init with no result pointer sets field result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
AstGen: handle `ty` result location for struct and array init correctly
Well, this was a journey!
The original issue I was trying to fix is covered by the new behavior
test in array.zig: in essence, `ty` and `coerced_ty` result locations
were not correctly propagated.
While fixing this, I noticed a similar bug in struct inits: the type was
propagated to *fields* fine, but the actual struct init was
unnecessarily anonymous, which could lead to unnecessary copies. Note
that the behavior test added in struct.zig was already passing - the bug
here didn't change any easy-to-test behavior - but I figured I'd add it
anyway.
This is a little harder than it seems, because the result type may not
itself be an array/struct type: it could be an optional / error union
wrapper. A new ZIR instruction is introduced to unwrap these.
This is also made a little tricky by the fact that it's possible for
result types to be unknown at the time of semantic analysis (due to
`anytype` parameters), leading to generic poison. In these cases, we
must essentially downgrade to an anonymous initialization.
Fixing these issues exposed *another* bug, related to type resolution in
Sema. That issue is now tracked by #16603. As a temporary workaround for
this bug, a few result locations for builtin function operands have been
disabled in AstGen. This is technically a breaking change, but it's very
minor: I doubt it'll cause any breakage in the wild.
2023-07-29 06:03:51 +01:00
|
|
|
const S = struct {
|
|
|
|
|
// A function parameter has a result type, but no result pointer.
|
|
|
|
|
fn f(arr: [1]u32) u32 {
|
|
|
|
|
return arr[0];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const x: u64 = 123;
|
|
|
|
|
const y = S.f(.{@intCast(x)});
|
|
|
|
|
|
|
|
|
|
try expect(y == x);
|
|
|
|
|
}
|
2023-08-10 03:25:35 -04:00
|
|
|
|
|
|
|
|
test "runtime side-effects in comptime-known array init" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2023-08-10 03:25:35 -04:00
|
|
|
var side_effects: u4 = 0;
|
|
|
|
|
const init = [4]u4{
|
|
|
|
|
blk: {
|
|
|
|
|
side_effects += 1;
|
|
|
|
|
break :blk 1;
|
|
|
|
|
},
|
|
|
|
|
blk: {
|
|
|
|
|
side_effects += 2;
|
|
|
|
|
break :blk 2;
|
|
|
|
|
},
|
|
|
|
|
blk: {
|
|
|
|
|
side_effects += 4;
|
|
|
|
|
break :blk 4;
|
|
|
|
|
},
|
|
|
|
|
blk: {
|
|
|
|
|
side_effects += 8;
|
|
|
|
|
break :blk 8;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
try expectEqual([4]u4{ 1, 2, 4, 8 }, init);
|
|
|
|
|
try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
|
|
|
|
|
}
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
|
|
|
|
|
test "slice initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &my_u32, &my_u64 };
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
const foo: []const u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
test "sentinel-terminated slice initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
|
|
|
|
_ = .{ &my_u32, &my_u64 };
|
|
|
|
|
const foo: [:999]const u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try std.testing.expectEqualSentinel(u16, 999, &.{ 123, 456, 123, 456 }, foo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "many-item pointer initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
|
|
|
|
_ = .{ &my_u32, &my_u64 };
|
|
|
|
|
const foo: [*]const u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try expectEqual(123, foo[0]);
|
|
|
|
|
try expectEqual(456, foo[1]);
|
|
|
|
|
try expectEqual(123, foo[2]);
|
|
|
|
|
try expectEqual(456, foo[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "many-item sentinel-terminated pointer initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
|
|
|
|
_ = .{ &my_u32, &my_u64 };
|
|
|
|
|
const foo: [*:999]const u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try expectEqual(123, foo[0]);
|
|
|
|
|
try expectEqual(456, foo[1]);
|
|
|
|
|
try expectEqual(123, foo[2]);
|
|
|
|
|
try expectEqual(456, foo[3]);
|
|
|
|
|
try expectEqual(999, foo[4]);
|
|
|
|
|
}
|
|
|
|
|
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
test "pointer to array initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
2023-11-16 13:21:18 +00:00
|
|
|
_ = .{ &my_u32, &my_u64 };
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
const foo: *const [4]u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try std.testing.expectEqualSlices(u16, &.{ 123, 456, 123, 456 }, foo);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
test "pointer to sentinel-terminated array initialized through reference to anonymous array init provides result types" {
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
|
|
2024-02-13 22:30:14 +01:00
|
|
|
var my_u32: u32 = 123;
|
|
|
|
|
var my_u64: u64 = 456;
|
|
|
|
|
_ = .{ &my_u32, &my_u64 };
|
|
|
|
|
const foo: *const [4:999]u16 = &.{
|
|
|
|
|
@intCast(my_u32),
|
|
|
|
|
@intCast(my_u64),
|
|
|
|
|
@truncate(my_u32),
|
|
|
|
|
@truncate(my_u64),
|
|
|
|
|
};
|
|
|
|
|
try std.testing.expectEqualSentinel(u16, 999, &.{ 123, 456, 123, 456 }, foo);
|
|
|
|
|
}
|
|
|
|
|
|
compiler: preserve result type information through address-of operator
This commit introduces the new `ref_coerced_ty` result type into AstGen.
This represents a expression which we want to treat as an lvalue, and
the pointer will be coerced to a given type.
This change gives known result types to many expressions, in particular
struct and array initializations. This allows certain casts to work
which previously required explicitly specifying types via `@as`. It also
eliminates our dependence on anonymous struct types for expressions of
the form `&.{ ... }` - this paves the way for #16865, and also results
in less Sema magic happening for such initializations, also leading to
potentially better runtime code.
As part of these changes, this commit also implements #17194 by
disallowing RLS on explicitly-typed struct and array initializations.
Apologies for linking these changes - it seemed rather pointless to try
and separate them, since they both make big changes to struct and array
initializations in AstGen. The rationale for this change can be found in
the proposal - in essence, performing RLS whilst maintaining the
semantics of the intermediary type is a very difficult problem to solve.
This allowed the problematic `coerce_result_ptr` ZIR instruction to be
completely eliminated, which in turn also simplified the logic for
inferred allocations in Sema - thanks to this, we almost break even on
line count!
In doing this, the ZIR instructions surrounding these initializations
have been restructured - some have been added and removed, and others
renamed for clarity (and their semantics changed slightly). In order to
optimize ZIR tag count, the `struct_init_anon_ref` and
`array_init_anon_ref` instructions have been removed in favour of using
`ref` on a standard anonymous value initialization, since these
instructions are now virtually never used.
Lastly, it's worth noting that this commit introduces a slightly strange
source of generic poison types: in the expression `@as(*anyopaque, &x)`,
the sub-expression `x` has a generic poison result type, despite no
generic code being involved. This turns out to be a logical choice,
because we don't know the result type for `x`, and the generic poison
type represents precisely this case, providing the semantics we need.
Resolves: #16512
Resolves: #17194
2023-09-18 14:49:18 +01:00
|
|
|
test "tuple initialized through reference to anonymous array init provides result types" {
|
|
|
|
|
const Tuple = struct { u64, *const u32 };
|
|
|
|
|
const foo: *const Tuple = &.{
|
|
|
|
|
@intCast(12345),
|
|
|
|
|
@ptrFromInt(0x1000),
|
|
|
|
|
};
|
|
|
|
|
try expect(foo[0] == 12345);
|
|
|
|
|
try expect(@intFromPtr(foo[1]) == 0x1000);
|
|
|
|
|
}
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
test "copied array element doesn't alias source" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
var x: [10][10]u32 = undefined;
|
|
|
|
|
|
|
|
|
|
x[0][1] = 0;
|
|
|
|
|
const a = x[0];
|
|
|
|
|
x[0][1] = 15;
|
|
|
|
|
|
|
|
|
|
try expect(a[1] == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array initialized with string literal" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
a: u32,
|
|
|
|
|
c: [5]u8,
|
|
|
|
|
};
|
|
|
|
|
const U = union {
|
|
|
|
|
s: S,
|
|
|
|
|
};
|
|
|
|
|
const s_1 = S{
|
|
|
|
|
.a = undefined,
|
|
|
|
|
.c = "12345".*, // this caused problems
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var u_2 = U{ .s = s_1 };
|
|
|
|
|
_ = &u_2;
|
|
|
|
|
try std.testing.expectEqualStrings("12345", &u_2.s.c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "array initialized with array with sentinel" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
a: u32,
|
|
|
|
|
c: [5]u8,
|
|
|
|
|
};
|
|
|
|
|
const U = union {
|
|
|
|
|
s: S,
|
|
|
|
|
};
|
|
|
|
|
const c = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
|
|
|
const s_1 = S{
|
|
|
|
|
.a = undefined,
|
|
|
|
|
.c = c, // this caused problems
|
|
|
|
|
};
|
|
|
|
|
var u_2 = U{ .s = s_1 };
|
|
|
|
|
_ = &u_2;
|
|
|
|
|
try std.testing.expectEqualSlices(u8, &.{ 1, 2, 3, 4, 5 }, &u_2.s.c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "store array of array of structs at comptime" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
fn storeArrayOfArrayOfStructs() u8 {
|
|
|
|
|
const S = struct {
|
|
|
|
|
x: u8,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var cases = [_][1]S{
|
|
|
|
|
[_]S{
|
|
|
|
|
S{ .x = 15 },
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
_ = &cases;
|
|
|
|
|
return cases[0][0].x;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try expect(S.storeArrayOfArrayOfStructs() == 15);
|
2024-01-15 16:01:13 +11:00
|
|
|
comptime assert(S.storeArrayOfArrayOfStructs() == 15);
|
2024-01-02 17:33:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "accessing multidimensional global array at comptime" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
const S = struct {
|
|
|
|
|
const array = [_][]const []const u8{
|
|
|
|
|
&.{"hello"},
|
|
|
|
|
&.{ "world", "hello" },
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try std.testing.expect(S.array[0].len == 1);
|
|
|
|
|
try std.testing.expectEqualStrings("hello", S.array[0][0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
test "union that needs padding bytes inside an array" {
|
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-01-02 17:33:41 +02:00
|
|
|
|
|
|
|
|
const B = union(enum) {
|
|
|
|
|
D: u8,
|
|
|
|
|
E: u16,
|
|
|
|
|
};
|
|
|
|
|
const A = union(enum) {
|
|
|
|
|
B: B,
|
|
|
|
|
C: u8,
|
|
|
|
|
};
|
|
|
|
|
var as = [_]A{
|
|
|
|
|
A{ .B = B{ .D = 1 } },
|
|
|
|
|
A{ .B = B{ .D = 1 } },
|
|
|
|
|
};
|
|
|
|
|
_ = &as;
|
|
|
|
|
|
|
|
|
|
const a = as[0].B;
|
|
|
|
|
try std.testing.expect(a.D == 1);
|
|
|
|
|
}
|
2024-04-02 04:01:52 -04:00
|
|
|
|
|
|
|
|
test "runtime index of array of zero-bit values" {
|
2024-04-05 00:13:48 +03:30
|
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
2024-04-13 23:11:32 -07:00
|
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
2024-04-05 00:13:48 +03:30
|
|
|
|
2024-04-02 04:01:52 -04:00
|
|
|
var runtime: struct { array: [1]void, index: usize } = undefined;
|
|
|
|
|
runtime = .{ .array = .{{}}, .index = 0 };
|
|
|
|
|
const result = struct { index: usize, value: void }{
|
|
|
|
|
.index = runtime.index,
|
|
|
|
|
.value = runtime.array[runtime.index],
|
|
|
|
|
};
|
|
|
|
|
try std.testing.expect(result.index == 0);
|
|
|
|
|
try std.testing.expect(result.value == {});
|
|
|
|
|
}
|