aboutsummaryrefslogtreecommitdiff
path: root/test/behavior
diff options
context:
space:
mode:
authorMitchell Hashimoto <mitchell.hashimoto@gmail.com>2022-03-16 12:21:48 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-16 16:26:54 -0700
commit418197b6c51b99ee2a0be5e394753868f7dbf982 (patch)
tree0cd552ad21afc0d61827a8ad248ef50e2cbbaa85 /test/behavior
parent94672dfb1941289eb65fdeab2e1dcc39ca70c3b7 (diff)
downloadzig-418197b6c51b99ee2a0be5e394753868f7dbf982.tar.gz
zig-418197b6c51b99ee2a0be5e394753868f7dbf982.zip
stage2: elem_ptr needs to know if slice or direct access
This fixes one of the major issues plaguing the `std.sort` comptime tests. The high level issue is that at comptime, we need to know whether `elem_ptr` is being used to subslice an array-like pointer or access a child value. High-level example: var x: [2][2]i32 = undefined; var a = &x[0]; // elem_ptr, type *[2]i32 var y: [5]i32 = undefined; var b = y[1..3]; // elem_ptr, type *[2]i32 `a` is pointing directly to the 0th element of `x`. But `b` is subslicing the 1st and 2nd element of `y`. At runtime with a well defined memory layout, this is an inconsequential detail. At comptime, the values aren't laid out exactly in-memory so we need to know the difference. This becomes an issue specifically in this case: var c: []i32 = a; var d: []i32 = b; When converting the `*[N]T` to `[]T` we need to know what array to point to. For runtime, its all the same. For comptime, we need to know if its the parent array or the child value. See the behavior tests for more details. This commit fixes this by adding a boolean to track this on the `elem_ptr`. We can't just immediately deref the child for `&x[0]` because it is legal to ptrCast it to a many-pointer, do arithmetic, and then cast it back (see behavior test) so we need to retain access to the "parent" indexable.
Diffstat (limited to 'test/behavior')
-rw-r--r--test/behavior/pointers.zig68
1 files changed, 68 insertions, 0 deletions
diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig
index 74089611db..96200e73fc 100644
--- a/test/behavior/pointers.zig
+++ b/test/behavior/pointers.zig
@@ -437,3 +437,71 @@ test "indexing array with sentinel returns correct type" {
var s: [:0]const u8 = "abc";
try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
}
+
+test "element pointer to slice" {
+ if (builtin.zig_backend == .stage2_c) 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 {
+ var cases: [2][2]i32 = [_][2]i32{
+ [_]i32{ 0, 1 },
+ [_]i32{ 2, 3 },
+ };
+
+ const items: []i32 = &cases[0]; // *[2]i32
+ try testing.expect(items.len == 2);
+ try testing.expect(items[1] == 1);
+ try testing.expect(items[0] == 0);
+ }
+ };
+
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "element pointer arithmetic to slice" {
+ if (builtin.zig_backend == .stage2_c) 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 {
+ var cases: [2][2]i32 = [_][2]i32{
+ [_]i32{ 0, 1 },
+ [_]i32{ 2, 3 },
+ };
+
+ const elem_ptr = &cases[0]; // *[2]i32
+ const many = @ptrCast([*][2]i32, elem_ptr);
+ const many_elem = @ptrCast(*[2]i32, &many[1]);
+ const items: []i32 = many_elem;
+ try testing.expect(items.len == 2);
+ try testing.expect(items[1] == 3);
+ try testing.expect(items[0] == 2);
+ }
+ };
+
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}
+
+test "array slicing to slice" {
+ if (builtin.zig_backend == .stage2_c) 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 {
+ var str: [5]i32 = [_]i32{ 1, 2, 3, 4, 5 };
+ var sub: *[2]i32 = str[1..3];
+ var slice: []i32 = sub; // used to cause failures
+ try testing.expect(slice.len == 2);
+ try testing.expect(slice[0] == 2);
+ }
+ };
+
+ try S.doTheTest();
+ comptime try S.doTheTest();
+}