aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-03 23:57:05 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-02-03 23:59:32 -0700
commit95fbce2b958395a367a82ce33170edd93e686173 (patch)
treedae1e68036754591c53b71571d5b12b3b2f33539
parent64f7231f86d4b8a155f48087b3f173d8e41b620c (diff)
downloadzig-95fbce2b958395a367a82ce33170edd93e686173.tar.gz
zig-95fbce2b958395a367a82ce33170edd93e686173.zip
Sema: fixes to fieldVal, resolveStructFully, Type.eql
fieldVal handles pointer to pointer to array. This can happen for example, if a pointer to an array is used as the condition expression of a for loop. resolveStructFully handles tuples (by doing nothing). fixed Type comparison for tuples to handle comptime fields properly.
-rw-r--r--src/Sema.zig62
-rw-r--r--src/type.zig14
-rw-r--r--test/behavior.zig1
-rw-r--r--test/behavior/slice.zig352
-rw-r--r--test/behavior/slice_stage1.zig347
5 files changed, 405 insertions, 371 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 7666b2c9ec..c4b3ad8c33 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12998,7 +12998,7 @@ fn fieldVal(
.Array => {
if (mem.eql(u8, field_name, "len")) {
return sema.addConstant(
- Type.initTag(.comptime_int),
+ Type.comptime_int,
try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),
);
} else {
@@ -13010,26 +13010,43 @@ fn fieldVal(
);
}
},
- .Pointer => if (inner_ty.isSlice()) {
- if (mem.eql(u8, field_name, "ptr")) {
- const slice = if (is_pointer_to)
- try sema.analyzeLoad(block, src, object, object_src)
- else
- object;
- return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
- } else if (mem.eql(u8, field_name, "len")) {
- const slice = if (is_pointer_to)
- try sema.analyzeLoad(block, src, object, object_src)
- else
- object;
- return sema.analyzeSliceLen(block, src, slice);
- } else {
- return sema.fail(
- block,
- field_name_src,
- "no member named '{s}' in '{}'",
- .{ field_name, object_ty },
- );
+ .Pointer => {
+ const ptr_info = inner_ty.ptrInfo().data;
+ if (ptr_info.size == .Slice) {
+ if (mem.eql(u8, field_name, "ptr")) {
+ const slice = if (is_pointer_to)
+ try sema.analyzeLoad(block, src, object, object_src)
+ else
+ object;
+ return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
+ } else if (mem.eql(u8, field_name, "len")) {
+ const slice = if (is_pointer_to)
+ try sema.analyzeLoad(block, src, object, object_src)
+ else
+ object;
+ return sema.analyzeSliceLen(block, src, slice);
+ } else {
+ return sema.fail(
+ block,
+ field_name_src,
+ "no member named '{s}' in '{}'",
+ .{ field_name, object_ty },
+ );
+ }
+ } else if (ptr_info.pointee_type.zigTypeTag() == .Array) {
+ if (mem.eql(u8, field_name, "len")) {
+ return sema.addConstant(
+ Type.comptime_int,
+ try Value.Tag.int_u64.create(arena, ptr_info.pointee_type.arrayLen()),
+ );
+ } else {
+ return sema.fail(
+ block,
+ field_name_src,
+ "no member named '{s}' in '{}'",
+ .{ field_name, ptr_info.pointee_type },
+ );
+ }
}
},
.Type => {
@@ -16371,7 +16388,8 @@ fn resolveStructFully(
try resolveStructLayout(sema, block, src, ty);
const resolved_ty = try sema.resolveTypeFields(block, src, ty);
- const struct_obj = resolved_ty.castTag(.@"struct").?.data;
+ const payload = resolved_ty.castTag(.@"struct") orelse return;
+ const struct_obj = payload.data;
switch (struct_obj.status) {
.none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
.fully_resolved_wip, .fully_resolved => return,
diff --git a/src/type.zig b/src/type.zig
index 272d09a921..e3a4b3d60a 100644
--- a/src/type.zig
+++ b/src/type.zig
@@ -634,7 +634,19 @@ pub const Type = extern union {
for (a_payload.data.values) |a_val, i| {
const ty = a_payload.data.types[i];
const b_val = b_payload.data.values[i];
- if (!Value.eql(a_val, b_val, ty)) return false;
+ if (a_val.tag() == .unreachable_value) {
+ if (b_val.tag() == .unreachable_value) {
+ continue;
+ } else {
+ return false;
+ }
+ } else {
+ if (b_val.tag() == .unreachable_value) {
+ return false;
+ } else {
+ if (!Value.eql(a_val, b_val, ty)) return false;
+ }
+ }
}
return true;
diff --git a/test/behavior.zig b/test/behavior.zig
index 0f74ed7d59..7b6cb6b402 100644
--- a/test/behavior.zig
+++ b/test/behavior.zig
@@ -163,7 +163,6 @@ test {
_ = @import("behavior/select.zig");
_ = @import("behavior/shuffle.zig");
_ = @import("behavior/sizeof_and_typeof_stage1.zig");
- _ = @import("behavior/slice_stage1.zig");
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
_ = @import("behavior/switch_prong_err_enum.zig");
diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig
index d4e8284751..4ec5f11817 100644
--- a/test/behavior/slice.zig
+++ b/test/behavior/slice.zig
@@ -204,3 +204,355 @@ test "slice string literal has correct type" {
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_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" {
+ 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" {
+ 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" {
+ 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" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ 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" {
+ 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_c) return error.SkipZigTest; // TODO
+
+ // 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" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ 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 expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
+ try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
+ try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
+ }
+ };
+
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "@ptrCast slice to pointer" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ 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 != .stage1) 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 testSliceZ();
+ try testSlice0();
+ 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);
+ comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
+ }
+
+ fn testSlice0() !void {
+ {
+ 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);
+ }
+ }
+
+ 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 "type coercion of pointer to anon struct literal to pointer to slice" {
+ if (builtin.zig_backend != .stage1) 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 slice" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ comptime {
+ var a: []const u8 = "aoeu";
+ var b: []const u8 = "asdf";
+ const c = a ++ b;
+ try expect(std.mem.eql(u8, c, "aoeuasdf"));
+ }
+}
+
+test "slice bounds in comptime concatenation" {
+ if (builtin.zig_backend != .stage1) 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" {
+ if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
+
+ {
+ 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);
+ }
+}
diff --git a/test/behavior/slice_stage1.zig b/test/behavior/slice_stage1.zig
deleted file mode 100644
index cb7c0f5223..0000000000
--- a/test/behavior/slice_stage1.zig
+++ /dev/null
@@ -1,347 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const expectEqualSlices = std.testing.expectEqualSlices;
-const expectEqual = std.testing.expectEqual;
-const mem = std.mem;
-
-test "result location zero sized array inside struct field implicit cast to slice" {
- const E = struct {
- entries: []u32,
- };
- var foo = E{ .entries = &[_]u32{} };
- try expect(foo.entries.len == 0);
-}
-
-const x = @intToPtr([*]i32, 0x1000)[0..0x500];
-const y = x[0x100..];
-test "compile time slice of pointer to hard coded address" {
- try expect(@ptrToInt(x) == 0x1000);
- try expect(x.len == 0x500);
-
- try expect(@ptrToInt(y) == 0x1100);
- try expect(y.len == 0x400);
-}
-
-test "runtime safety lets us slice from len..len" {
- 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" {
- var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
- var len: u32 = 10;
- var slice = buf[0..len];
- try expectEqualSlices(u8, "kjdhfkjdhf", slice);
-}
-
-test "C pointer slice access" {
- 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 expectEqual(@as(u32, 42), cl.*);
- }
-}
-
-fn sliceSum(comptime q: []const u8) i32 {
- comptime var result = 0;
- inline for (q) |item| {
- result += item;
- }
- return result;
-}
-
-test "comptime slices are disambiguated" {
- try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
- try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
-}
-
-test "slice type with custom alignment" {
- 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" {
- // 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 expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
- try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
- try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
- }
- };
-
- try S.doTheTest();
- comptime try S.doTheTest();
-}
-
-test "@ptrCast slice to pointer" {
- 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" {
- 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 testSliceZ();
- try testSlice0();
- 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);
- comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
- }
-
- fn testSlice0() !void {
- {
- 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);
- }
- }
-
- 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 "type coercion of pointer to anon struct literal to pointer to slice" {
- 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 slice" {
- comptime {
- var a: []const u8 = "aoeu";
- var b: []const u8 = "asdf";
- const c = a ++ b;
- try expect(std.mem.eql(u8, c, "aoeuasdf"));
- }
-}
-
-test "slice bounds in comptime concatenation" {
- 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);
- }
-}