mirror of
https://github.com/ziglang/zig.git
synced 2025-12-20 13:13:16 +00:00
The runtime behavior allowed this in both stage1 and stage2, but stage1 fails with index out of bounds during comptime. This behavior makes sense to support, and comptime behavior should match runtime behavior. I implement this fix only in stage2.
686 lines
22 KiB
Zig
686 lines
22 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
const expectEqualSlices = std.testing.expectEqualSlices;
|
|
const expectEqual = std.testing.expectEqual;
|
|
const mem = std.mem;
|
|
|
|
// comptime array passed as slice argument
|
|
comptime {
|
|
const S = struct {
|
|
fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
|
|
var i: usize = start_index;
|
|
while (i < slice.len) : (i += 1) {
|
|
if (slice[i] == value) return i;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
|
|
return indexOfScalarPos(T, slice, 0, value);
|
|
}
|
|
};
|
|
const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
|
|
const list: []const type = &unsigned;
|
|
var pos = S.indexOfScalar(type, list, c_ulong).?;
|
|
if (pos != 1) @compileError("bad pos");
|
|
}
|
|
|
|
test "slicing" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
var array: [20]i32 = undefined;
|
|
|
|
array[5] = 1234;
|
|
|
|
var slice = array[5..10];
|
|
|
|
if (slice.len != 5) unreachable;
|
|
|
|
const ptr = &slice[0];
|
|
if (ptr.* != 1234) unreachable;
|
|
|
|
var slice_rest = array[10..];
|
|
if (slice_rest.len != 10) unreachable;
|
|
}
|
|
|
|
test "const slice" {
|
|
comptime {
|
|
const a = "1234567890";
|
|
try expect(a.len == 10);
|
|
const b = a[1..2];
|
|
try expect(b.len == 1);
|
|
try expect(b[0] == '2');
|
|
}
|
|
}
|
|
|
|
test "comptime slice of undefined pointer of length 0" {
|
|
const slice1 = @as([*]i32, undefined)[0..0];
|
|
try expect(slice1.len == 0);
|
|
const slice2 = @as([*]i32, undefined)[100..100];
|
|
try expect(slice2.len == 0);
|
|
}
|
|
|
|
test "implicitly cast array of size 0 to slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
var msg = [_]u8{};
|
|
try assertLenIsZero(&msg);
|
|
}
|
|
|
|
fn assertLenIsZero(msg: []const u8) !void {
|
|
try expect(msg.len == 0);
|
|
}
|
|
|
|
test "access len index of sentinel-terminated slice" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var slice: [:0]const u8 = "hello";
|
|
|
|
try expect(slice.len == 5);
|
|
try expect(slice[5] == 0);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "comptime slice of slice preserves comptime var" {
|
|
comptime {
|
|
var buff: [10]u8 = undefined;
|
|
buff[0..][0..][0] = 1;
|
|
try expect(buff[0..][0..][0] == 1);
|
|
}
|
|
}
|
|
|
|
test "slice of type" {
|
|
comptime {
|
|
var types_array = [_]type{ i32, f64, type };
|
|
for (types_array) |T, i| {
|
|
switch (i) {
|
|
0 => try expect(T == i32),
|
|
1 => try expect(T == f64),
|
|
2 => try expect(T == type),
|
|
else => unreachable,
|
|
}
|
|
}
|
|
for (types_array[0..]) |T, i| {
|
|
switch (i) {
|
|
0 => try expect(T == i32),
|
|
1 => try expect(T == f64),
|
|
2 => try expect(T == type),
|
|
else => unreachable,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
test "generic malloc free" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
|
|
const a = memAlloc(u8, 10) catch unreachable;
|
|
memFree(u8, a);
|
|
}
|
|
var some_mem: [100]u8 = undefined;
|
|
fn memAlloc(comptime T: type, n: usize) anyerror![]T {
|
|
return @ptrCast([*]T, &some_mem[0])[0..n];
|
|
}
|
|
fn memFree(comptime T: type, memory: []T) void {
|
|
_ = memory;
|
|
}
|
|
|
|
test "slice of hardcoded address to pointer" {
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
const pointer = @intToPtr([*]u8, 0x04)[0..2];
|
|
comptime try expect(@TypeOf(pointer) == *[2]u8);
|
|
const slice: []const u8 = pointer;
|
|
try expect(@ptrToInt(slice.ptr) == 4);
|
|
try expect(slice.len == 2);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
}
|
|
|
|
test "comptime slice of pointer preserves comptime var" {
|
|
comptime {
|
|
var buff: [10]u8 = undefined;
|
|
var a = @ptrCast([*]u8, &buff);
|
|
a[0..1][0] = 1;
|
|
try expect(buff[0..][0..][0] == 1);
|
|
}
|
|
}
|
|
|
|
test "comptime pointer cast array and then slice" {
|
|
const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
|
|
const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
|
|
const sliceA: []const u8 = ptrA[0..2];
|
|
|
|
const ptrB: [*]const u8 = &array;
|
|
const sliceB: []const u8 = ptrB[0..2];
|
|
|
|
try expect(sliceA[1] == 2);
|
|
try expect(sliceB[1] == 2);
|
|
}
|
|
|
|
test "slicing zero length array" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
|
|
const s1 = ""[0..];
|
|
const s2 = ([_]u32{})[0..];
|
|
try expect(s1.len == 0);
|
|
try expect(s2.len == 0);
|
|
try expect(mem.eql(u8, s1, ""));
|
|
try expect(mem.eql(u32, s2, &[_]u32{}));
|
|
}
|
|
|
|
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
|
|
const y = x[0x100..];
|
|
test "compile time slice of pointer to hard coded address" {
|
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
|
|
try expect(@ptrToInt(x) == 0x1000);
|
|
try expect(x.len == 0x500);
|
|
|
|
try expect(@ptrToInt(y) == 0x1400);
|
|
try expect(y.len == 0x400);
|
|
}
|
|
|
|
test "slice string literal has correct type" {
|
|
comptime {
|
|
try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
|
|
const array = [_]i32{ 1, 2, 3, 4 };
|
|
try expect(@TypeOf(array[0..]) == *const [4]i32);
|
|
}
|
|
var runtime_zero: usize = 0;
|
|
comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
|
|
const array = [_]i32{ 1, 2, 3, 4 };
|
|
comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
|
|
}
|
|
|
|
test "result location zero sized array inside struct field implicit cast to slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
|
|
const E = struct {
|
|
entries: []u32,
|
|
};
|
|
var foo = E{ .entries = &[_]u32{} };
|
|
try expect(foo.entries.len == 0);
|
|
}
|
|
|
|
test "runtime safety lets us slice from len..len" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
var an_array = [_]u8{ 1, 2, 3 };
|
|
try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
|
|
}
|
|
|
|
fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
|
|
return a_slice[start..end];
|
|
}
|
|
|
|
test "C pointer" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
|
|
var len: u32 = 10;
|
|
var slice = buf[0..len];
|
|
try expect(mem.eql(u8, "kjdhfkjdhf", slice));
|
|
}
|
|
|
|
test "C pointer slice access" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
|
|
|
var buf: [10]u32 = [1]u32{42} ** 10;
|
|
const c_ptr = @ptrCast([*c]const u32, &buf);
|
|
|
|
var runtime_zero: usize = 0;
|
|
comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
|
|
comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
|
|
|
|
for (c_ptr[0..5]) |*cl| {
|
|
try expect(@as(u32, 42) == cl.*);
|
|
}
|
|
}
|
|
|
|
test "comptime slices are disambiguated" {
|
|
try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
|
|
try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
|
|
}
|
|
|
|
fn sliceSum(comptime q: []const u8) i32 {
|
|
comptime var result = 0;
|
|
inline for (q) |item| {
|
|
result += item;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
test "slice type with custom alignment" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
const LazilyResolvedType = struct {
|
|
anything: i32,
|
|
};
|
|
var slice: []align(32) LazilyResolvedType = undefined;
|
|
var array: [10]LazilyResolvedType align(32) = undefined;
|
|
slice = &array;
|
|
slice[1].anything = 42;
|
|
try expect(array[1].anything == 42);
|
|
}
|
|
|
|
test "obtaining a null terminated slice" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
// here we have a normal array
|
|
var buf: [50]u8 = undefined;
|
|
|
|
buf[0] = 'a';
|
|
buf[1] = 'b';
|
|
buf[2] = 'c';
|
|
buf[3] = 0;
|
|
|
|
// now we obtain a null terminated slice:
|
|
const ptr = buf[0..3 :0];
|
|
_ = ptr;
|
|
|
|
var runtime_len: usize = 3;
|
|
const ptr2 = buf[0..runtime_len :0];
|
|
// ptr2 is a null-terminated slice
|
|
comptime try expect(@TypeOf(ptr2) == [:0]u8);
|
|
comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
|
|
var runtime_zero: usize = 0;
|
|
comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
|
|
}
|
|
|
|
test "empty array to slice" {
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
const empty: []align(16) u8 = &[_]u8{};
|
|
const align_1: []align(1) u8 = empty;
|
|
const align_4: []align(4) u8 = empty;
|
|
const align_16: []align(16) u8 = empty;
|
|
try expect(1 == @typeInfo(@TypeOf(align_1)).Pointer.alignment);
|
|
try expect(4 == @typeInfo(@TypeOf(align_4)).Pointer.alignment);
|
|
try expect(16 == @typeInfo(@TypeOf(align_16)).Pointer.alignment);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "@ptrCast slice to pointer" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
var slice: []u8 = &array;
|
|
var ptr = @ptrCast(*u16, slice);
|
|
try expect(ptr.* == 65535);
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "slice syntax resulting in pointer-to-array" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try testArray();
|
|
try testArrayZ();
|
|
try testArray0();
|
|
try testArrayAlign();
|
|
try testPointer();
|
|
try testPointerZ();
|
|
try testPointer0();
|
|
try testPointerAlign();
|
|
try testSlice();
|
|
try testSliceOpt();
|
|
try testSliceAlign();
|
|
}
|
|
|
|
fn testArray() !void {
|
|
var array = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var slice = array[1..3];
|
|
comptime try expect(@TypeOf(slice) == *[2]u8);
|
|
try expect(slice[0] == 2);
|
|
try expect(slice[1] == 3);
|
|
}
|
|
|
|
fn testArrayZ() !void {
|
|
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
|
|
comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
|
|
comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
|
|
comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
|
|
}
|
|
|
|
fn testArray0() !void {
|
|
{
|
|
var array = [0]u8{};
|
|
var slice = array[0..0];
|
|
comptime try expect(@TypeOf(slice) == *[0]u8);
|
|
}
|
|
{
|
|
var array = [0:0]u8{};
|
|
var slice = array[0..0];
|
|
comptime try expect(@TypeOf(slice) == *[0:0]u8);
|
|
try expect(slice[0] == 0);
|
|
}
|
|
}
|
|
|
|
fn testArrayAlign() !void {
|
|
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var slice = array[4..5];
|
|
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
|
|
try expect(slice[0] == 5);
|
|
comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
|
|
}
|
|
|
|
fn testPointer() !void {
|
|
var array = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var pointer: [*]u8 = &array;
|
|
var slice = pointer[1..3];
|
|
comptime try expect(@TypeOf(slice) == *[2]u8);
|
|
try expect(slice[0] == 2);
|
|
try expect(slice[1] == 3);
|
|
}
|
|
|
|
fn testPointerZ() !void {
|
|
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
var pointer: [*:0]u8 = &array;
|
|
comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
|
|
comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
|
|
}
|
|
|
|
fn testPointer0() !void {
|
|
var pointer: [*]const u0 = &[1]u0{0};
|
|
var slice = pointer[0..1];
|
|
comptime try expect(@TypeOf(slice) == *const [1]u0);
|
|
try expect(slice[0] == 0);
|
|
}
|
|
|
|
fn testPointerAlign() !void {
|
|
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var pointer: [*]align(4) u8 = &array;
|
|
var slice = pointer[4..5];
|
|
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
|
|
try expect(slice[0] == 5);
|
|
comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
|
|
}
|
|
|
|
fn testSlice() !void {
|
|
var array = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var src_slice: []u8 = &array;
|
|
var slice = src_slice[1..3];
|
|
comptime try expect(@TypeOf(slice) == *[2]u8);
|
|
try expect(slice[0] == 2);
|
|
try expect(slice[1] == 3);
|
|
}
|
|
|
|
fn testSliceZ() !void {
|
|
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
var slice: [:0]u8 = &array;
|
|
comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
|
|
comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
|
|
comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
|
|
}
|
|
|
|
fn testSliceOpt() !void {
|
|
var array: [2]u8 = [2]u8{ 1, 2 };
|
|
var slice: ?[]u8 = &array;
|
|
comptime try expect(@TypeOf(&array, slice) == ?[]u8);
|
|
if (builtin.zig_backend != .stage1) {
|
|
// stage1 is not passing this case
|
|
comptime try expect(@TypeOf(slice, &array) == ?[]u8);
|
|
}
|
|
comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
|
|
}
|
|
|
|
fn testSliceAlign() !void {
|
|
var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
|
|
var src_slice: []align(4) u8 = &array;
|
|
var slice = src_slice[4..5];
|
|
comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
|
|
try expect(slice[0] == 5);
|
|
comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
|
|
}
|
|
|
|
fn testConcatStrLiterals() !void {
|
|
try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
|
|
try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "slice pointer-to-array null terminated" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
comptime {
|
|
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
var slice: [:0]u8 = &array;
|
|
try expect(@TypeOf(slice[1..3]) == *[2]u8);
|
|
try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
|
|
|
|
if (builtin.zig_backend == .stage1) {
|
|
try expect(@TypeOf(slice[1..]) == [:0]u8);
|
|
} else {
|
|
// stage2 gives a more accurate, correct answer
|
|
try expect(@TypeOf(slice[1..]) == *[4:0]u8);
|
|
}
|
|
}
|
|
|
|
var array = [5:0]u8{ 1, 2, 3, 4, 5 };
|
|
var slice: [:0]u8 = &array;
|
|
comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
|
|
comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
|
|
comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
|
|
}
|
|
|
|
test "slice pointer-to-array zero length" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
comptime {
|
|
{
|
|
var array = [0]u8{};
|
|
var src_slice: []u8 = &array;
|
|
var slice = src_slice[0..0];
|
|
try expect(@TypeOf(slice) == *[0]u8);
|
|
}
|
|
{
|
|
var array = [0:0]u8{};
|
|
var src_slice: [:0]u8 = &array;
|
|
var slice = src_slice[0..0];
|
|
if (builtin.zig_backend == .stage1) {
|
|
try expect(@TypeOf(slice) == *[0]u8);
|
|
} else {
|
|
// stage2 gives a more accurate, correct answer
|
|
try expect(@TypeOf(slice) == *[0:0]u8);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
var array = [0]u8{};
|
|
var src_slice: []u8 = &array;
|
|
var slice = src_slice[0..0];
|
|
comptime try expect(@TypeOf(slice) == *[0]u8);
|
|
}
|
|
{
|
|
var array = [0:0]u8{};
|
|
var src_slice: [:0]u8 = &array;
|
|
var slice = src_slice[0..0];
|
|
comptime try expect(@TypeOf(slice) == *[0]u8);
|
|
}
|
|
}
|
|
|
|
test "type coercion of pointer to anon struct literal to pointer to slice" {
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const U = union {
|
|
a: u32,
|
|
b: bool,
|
|
c: []const u8,
|
|
};
|
|
|
|
fn doTheTest() !void {
|
|
var x1: u8 = 42;
|
|
const t1 = &.{ x1, 56, 54 };
|
|
var slice1: []const u8 = t1;
|
|
try expect(slice1.len == 3);
|
|
try expect(slice1[0] == 42);
|
|
try expect(slice1[1] == 56);
|
|
try expect(slice1[2] == 54);
|
|
|
|
var x2: []const u8 = "hello";
|
|
const t2 = &.{ x2, ", ", "world!" };
|
|
// @compileLog(@TypeOf(t2));
|
|
var slice2: []const []const u8 = t2;
|
|
try expect(slice2.len == 3);
|
|
try expect(mem.eql(u8, slice2[0], "hello"));
|
|
try expect(mem.eql(u8, slice2[1], ", "));
|
|
try expect(mem.eql(u8, slice2[2], "world!"));
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
comptime try S.doTheTest();
|
|
}
|
|
|
|
test "array concat of slices gives ptr to array" {
|
|
comptime {
|
|
var a: []const u8 = "aoeu";
|
|
var b: []const u8 = "asdf";
|
|
const c = a ++ b;
|
|
try expect(std.mem.eql(u8, c, "aoeuasdf"));
|
|
if (builtin.zig_backend != .stage1) {
|
|
// spec change: array concat now returns pointer-to-array for slices
|
|
try expect(@TypeOf(c) == *const [8]u8);
|
|
}
|
|
}
|
|
}
|
|
|
|
test "array mult of slice gives ptr to array" {
|
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest; // Stage 1 does not support multiplying slices
|
|
|
|
comptime {
|
|
var a: []const u8 = "aoeu";
|
|
const c = a ** 2;
|
|
try expect(std.mem.eql(u8, c, "aoeuaoeu"));
|
|
try expect(@TypeOf(c) == *const [8]u8);
|
|
}
|
|
}
|
|
|
|
test "slice bounds in comptime concatenation" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
|
|
const bs = comptime blk: {
|
|
const b = "........1........";
|
|
break :blk b[8..9];
|
|
};
|
|
const str = "" ++ bs;
|
|
try expect(str.len == 1);
|
|
try expect(std.mem.eql(u8, str, "1"));
|
|
|
|
const str2 = bs ++ "";
|
|
try expect(str2.len == 1);
|
|
try expect(std.mem.eql(u8, str2, "1"));
|
|
}
|
|
|
|
test "slice sentinel access at comptime" {
|
|
{
|
|
const str0 = &[_:0]u8{ '1', '2', '3' };
|
|
const slice0: [:0]const u8 = str0;
|
|
|
|
try expect(slice0.len == 3);
|
|
try expect(slice0[slice0.len] == 0);
|
|
}
|
|
{
|
|
const str0 = "123";
|
|
_ = &str0[0];
|
|
const slice0: [:0]const u8 = str0;
|
|
|
|
try expect(slice0.len == 3);
|
|
try expect(slice0[slice0.len] == 0);
|
|
}
|
|
}
|
|
|
|
test "slicing array with sentinel as end index" {
|
|
// Doesn't work in stage1
|
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn do() !void {
|
|
var array = [_:0]u8{ 1, 2, 3, 4 };
|
|
var slice = array[4..5];
|
|
try expect(slice.len == 1);
|
|
try expect(slice[0] == 0);
|
|
try expect(@TypeOf(slice) == *[1]u8);
|
|
}
|
|
};
|
|
|
|
try S.do();
|
|
comptime try S.do();
|
|
}
|
|
|
|
test "slicing slice with sentinel as end index" {
|
|
// Doesn't work in stage1
|
|
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn do() !void {
|
|
var array = [_:0]u8{ 1, 2, 3, 4 };
|
|
var src_slice: [:0]u8 = &array;
|
|
var slice = src_slice[4..5];
|
|
try expect(slice.len == 1);
|
|
try expect(slice[0] == 0);
|
|
try expect(@TypeOf(slice) == *[1]u8);
|
|
}
|
|
};
|
|
|
|
try S.do();
|
|
comptime try S.do();
|
|
}
|