1const builtin = @import("builtin");
2const std = @import("std");
3const assert = std.debug.assert;
4const expect = std.testing.expect;
5const expectEqualSlices = std.testing.expectEqualSlices;
6const expectEqualStrings = std.testing.expectEqualStrings;
7const expectEqual = std.testing.expectEqual;
8const mem = std.mem;
9
10// comptime array passed as slice argument
11comptime {
12 const S = struct {
13 fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
14 var i: usize = start_index;
15 while (i < slice.len) : (i += 1) {
16 if (slice[i] == value) return i;
17 }
18 return null;
19 }
20
21 fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
22 return indexOfScalarPos(T, slice, 0, value);
23 }
24 };
25 const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
26 const list: []const type = &unsigned;
27 const pos = S.indexOfScalar(type, list, c_ulong).?;
28 if (pos != 1) @compileError("bad pos");
29}
30
31test "slicing" {
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
34
35 var array: [20]i32 = undefined;
36
37 array[5] = 1234;
38
39 var slice = array[5..10];
40
41 try expect(slice.len == 5);
42
43 const ptr = &slice[0];
44 try expect(ptr.* == 1234);
45
46 var slice_rest = array[10..];
47 _ = &slice_rest;
48 try expect(slice_rest.len == 10);
49}
50
51test "const slice" {
52 comptime {
53 const a = "1234567890";
54 try expect(a.len == 10);
55 const b = a[1..2];
56 try expect(b.len == 1);
57 try expect(b[0] == '2');
58 }
59}
60
61test "comptime slice of undefined pointer of length 0" {
62 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
63
64 const slice1 = @as([*]i32, undefined)[0..0];
65 try expect(slice1.len == 0);
66 const slice2 = @as([*]i32, undefined)[100..100];
67 try expect(slice2.len == 0);
68}
69
70test "implicitly cast array of size 0 to slice" {
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
73
74 var msg = [_]u8{};
75 try assertLenIsZero(&msg);
76}
77
78fn assertLenIsZero(msg: []const u8) !void {
79 try expect(msg.len == 0);
80}
81
82test "access len index of sentinel-terminated slice" {
83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
85
86 const S = struct {
87 fn doTheTest() !void {
88 var slice: [:0]const u8 = "hello";
89 _ = &slice;
90 try expect(slice.len == 5);
91 try expect(slice[5] == 0);
92 }
93 };
94 try S.doTheTest();
95 try comptime S.doTheTest();
96}
97
98test "comptime slice of slice preserves comptime var" {
99 comptime {
100 var buff: [10]u8 = undefined;
101 buff[0..][0..][0] = 1;
102 try expect(buff[0..][0..][0] == 1);
103 }
104}
105
106test "open slice of open slice with sentinel" {
107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
109
110 var slice: [:0]const u8 = "hello";
111 _ = &slice;
112
113 comptime assert(@TypeOf(slice[0..][0.. :0]) == [:0]const u8);
114 try expect(slice[0..][0.. :0].len == 5);
115 try expect(slice[0..][0.. :0][0] == 'h');
116 try expect(slice[0..][0.. :0][5] == 0);
117
118 comptime assert(@TypeOf(slice[1..][0.. :0]) == [:0]const u8);
119 try expect(slice[1..][0.. :0].len == 4);
120 try expect(slice[1..][0.. :0][0] == 'e');
121 try expect(slice[1..][0.. :0][4] == 0);
122}
123
124test "open slice with sentinel of slice with end index" {
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
127
128 var slice: [:0]const u8 = "hello";
129 _ = &slice;
130
131 comptime assert(@TypeOf(slice[0.. :0][0..5]) == *const [5]u8);
132 try expect(slice[0.. :0][0..5].len == 5);
133 try expect(slice[0.. :0][0..5][0] == 'h');
134 try expect(slice[0.. :0][0..5][4] == 'o');
135
136 comptime assert(@TypeOf(slice[0.. :0][0..5 :0]) == *const [5:0]u8);
137 try expect(slice[0.. :0][0..5 :0].len == 5);
138 try expect(slice[0.. :0][0..5 :0][0] == 'h');
139 try expect(slice[0.. :0][0..5 :0][5] == 0);
140}
141
142test "slice of type" {
143 comptime {
144 var types_array = [_]type{ i32, f64, type };
145 for (types_array, 0..) |T, i| {
146 switch (i) {
147 0 => try expect(T == i32),
148 1 => try expect(T == f64),
149 2 => try expect(T == type),
150 else => unreachable,
151 }
152 }
153 for (types_array[0..], 0..) |T, i| {
154 switch (i) {
155 0 => try expect(T == i32),
156 1 => try expect(T == f64),
157 2 => try expect(T == type),
158 else => unreachable,
159 }
160 }
161 }
162}
163
164test "pass a slice of types to a function" {
165 const S = struct {
166 fn checkTypesSlice(comptime types_slice: []const type) !void {
167 try expect(types_slice.len == 2);
168 try expect(types_slice[0] == anyerror);
169 try expect(types_slice[1] == bool);
170 }
171 };
172 const types_array = [_]type{ void, anyerror, bool };
173 try S.checkTypesSlice(types_array[1..]);
174}
175
176test "generic malloc free" {
177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
179
180 const a = memAlloc(u8, 10) catch unreachable;
181 memFree(u8, a);
182}
183var some_mem: [100]u8 = undefined;
184fn memAlloc(comptime T: type, n: usize) anyerror![]T {
185 return @as([*]T, @ptrCast(&some_mem[0]))[0..n];
186}
187fn memFree(comptime T: type, memory: []T) void {
188 _ = memory;
189}
190
191test "slice of hardcoded address to pointer" {
192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
193 const S = struct {
194 fn doTheTest() !void {
195 const pointer = @as([*]u8, @ptrFromInt(0x04))[0..2];
196 comptime assert(@TypeOf(pointer) == *[2]u8);
197 const slice: []const u8 = pointer;
198 try expect(@intFromPtr(slice.ptr) == 4);
199 try expect(slice.len == 2);
200 }
201 };
202
203 try S.doTheTest();
204}
205
206test "comptime slice of pointer preserves comptime var" {
207 comptime {
208 var buff: [10]u8 = undefined;
209 var a = @as([*]u8, @ptrCast(&buff));
210 a[0..1][0] = 1;
211 try expect(buff[0..][0..][0] == 1);
212 }
213}
214
215test "comptime pointer cast array and then slice" {
216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
217
218 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
219
220 const ptrA: [*]const u8 = @as([*]const u8, @ptrCast(&array));
221 const sliceA: []const u8 = ptrA[0..2];
222
223 const ptrB: [*]const u8 = &array;
224 const sliceB: []const u8 = ptrB[0..2];
225
226 try expect(sliceA[1] == 2);
227 try expect(sliceB[1] == 2);
228}
229
230test "slicing zero length array" {
231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
232 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
233 const s1 = ""[0..];
234 const s2 = ([_]u32{})[0..];
235 try expect(s1.len == 0);
236 try expect(s2.len == 0);
237 try expect(mem.eql(u8, s1, ""));
238 try expect(mem.eql(u32, s2, &[_]u32{}));
239}
240
241test "slicing pointer by length" {
242 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
243
244 const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
245 const ptr: [*]const u8 = @as([*]const u8, @ptrCast(&array));
246 const slice = ptr[1..][0..5];
247 try expect(slice.len == 5);
248 var i: usize = 0;
249 while (i < slice.len) : (i += 1) {
250 try expect(slice[i] == i + 2);
251 }
252}
253
254const x = @as([*]i32, @ptrFromInt(0x1000))[0..0x500];
255const y = x[0x100..];
256test "compile time slice of pointer to hard coded address" {
257 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
258
259 try expect(@intFromPtr(x) == 0x1000);
260 try expect(x.len == 0x500);
261
262 try expect(@intFromPtr(y) == 0x1400);
263 try expect(y.len == 0x400);
264}
265
266test "slice string literal has correct type" {
267 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
268
269 comptime {
270 try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
271 const array = [_]i32{ 1, 2, 3, 4 };
272 try expect(@TypeOf(array[0..]) == *const [4]i32);
273 }
274 var runtime_zero: usize = 0;
275 _ = &runtime_zero;
276 comptime assert(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
277 const array = [_]i32{ 1, 2, 3, 4 };
278 comptime assert(@TypeOf(array[runtime_zero..]) == []const i32);
279}
280
281test "result location zero sized array inside struct field implicit cast to slice" {
282 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
283 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
284
285 const E = struct {
286 entries: []u32,
287 };
288 var foo: E = .{ .entries = &[_]u32{} };
289 _ = &foo;
290 try expect(foo.entries.len == 0);
291}
292
293test "runtime safety lets us slice from len..len" {
294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
297
298 var an_array = [_]u8{ 1, 2, 3 };
299 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
300}
301
302fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
303 return a_slice[start..end];
304}
305
306test "C pointer" {
307 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
308 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
309
310 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
311 var len: u32 = 10;
312 _ = &len;
313 const slice = buf[0..len];
314 try expect(mem.eql(u8, "kjdhfkjdhf", slice));
315}
316
317test "C pointer slice access" {
318 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
319 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
321
322 var buf: [10]u32 = @splat(42);
323 const c_ptr = @as([*c]const u32, @ptrCast(&buf));
324
325 var runtime_zero: usize = 0;
326 _ = &runtime_zero;
327 comptime assert(@TypeOf(c_ptr[runtime_zero..1]) == []const u32);
328 comptime assert(@TypeOf(c_ptr[0..1]) == *const [1]u32);
329
330 for (c_ptr[0..5]) |*cl| {
331 try expect(@as(u32, 42) == cl.*);
332 }
333}
334
335test "comptime slices are disambiguated" {
336 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
337 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
338}
339
340fn sliceSum(comptime q: []const u8) i32 {
341 comptime var result = 0;
342 inline for (q) |item| {
343 result += item;
344 }
345 return result;
346}
347
348test "slice type with custom alignment" {
349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
350 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
351
352 const LazilyResolvedType = struct {
353 anything: i32,
354 };
355 var slice: []align(32) LazilyResolvedType = undefined;
356 var array: [10]LazilyResolvedType align(32) = undefined;
357 slice = &array;
358 slice[1].anything = 42;
359 try expect(array[1].anything == 42);
360}
361
362test "obtaining a null terminated slice" {
363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
365
366 // here we have a normal array
367 var buf: [50]u8 = undefined;
368
369 buf[0] = 'a';
370 buf[1] = 'b';
371 buf[2] = 'c';
372 buf[3] = 0;
373
374 // now we obtain a null terminated slice:
375 const ptr = buf[0..3 :0];
376 _ = ptr;
377
378 var runtime_len: usize = 3;
379 _ = &runtime_len;
380 const ptr2 = buf[0..runtime_len :0];
381 // ptr2 is a null-terminated slice
382 comptime assert(@TypeOf(ptr2) == [:0]u8);
383 comptime assert(@TypeOf(ptr2[0..2]) == *[2]u8);
384 var runtime_zero: usize = 0;
385 _ = &runtime_zero;
386 comptime assert(@TypeOf(ptr2[runtime_zero..2]) == []u8);
387}
388
389test "empty array to slice" {
390 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
391
392 const S = struct {
393 fn doTheTest() !void {
394 const empty: []align(16) u8 = &[_]u8{};
395 const align_1: []align(1) u8 = empty;
396 const align_4: []align(4) u8 = empty;
397 const align_16: []align(16) u8 = empty;
398 try expect(1 == @typeInfo(@TypeOf(align_1)).pointer.attrs.@"align");
399 try expect(4 == @typeInfo(@TypeOf(align_4)).pointer.attrs.@"align");
400 try expect(16 == @typeInfo(@TypeOf(align_16)).pointer.attrs.@"align");
401 }
402 };
403
404 try S.doTheTest();
405 try comptime S.doTheTest();
406}
407
408test "@ptrCast slice to pointer" {
409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
410 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
411
412 const S = struct {
413 fn doTheTest() !void {
414 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
415 const slice: []align(@alignOf(u16)) u8 = &array;
416 const ptr: *u16 = @ptrCast(slice);
417 try expect(ptr.* == 65535);
418 }
419 };
420
421 try S.doTheTest();
422 try comptime S.doTheTest();
423}
424
425test "slice multi-pointer without end" {
426 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
428
429 const S = struct {
430 fn doTheTest() !void {
431 try testPointer();
432 try testPointerZ();
433 }
434
435 fn testPointer() !void {
436 var array = [5]u8{ 1, 2, 3, 4, 5 };
437 const pointer: [*]u8 = &array;
438 const slice = pointer[1..];
439 comptime assert(@TypeOf(slice) == [*]u8);
440 try expect(slice[0] == 2);
441 try expect(slice[1] == 3);
442 }
443
444 fn testPointerZ() !void {
445 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
446 const pointer: [*:0]u8 = &array;
447
448 comptime assert(@TypeOf(pointer[1..]) == [*:0]u8);
449 comptime assert(@TypeOf(pointer[1.. :0]) == [*:0]u8);
450
451 const slice = pointer[1..];
452 comptime assert(@TypeOf(slice) == [*:0]u8);
453 try expect(slice[0] == 2);
454 try expect(slice[1] == 3);
455 }
456 };
457
458 try S.doTheTest();
459 try comptime S.doTheTest();
460}
461
462test "slice syntax resulting in pointer-to-array" {
463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
465 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
466
467 const S = struct {
468 fn doTheTest() !void {
469 try testArray();
470 try testArrayZ();
471 try testArray0();
472 try testArrayAlign();
473 try testPointer();
474 try testPointerZ();
475 try testPointer0();
476 try testPointerAlign();
477 try testSlice();
478 try testSliceZ();
479 try testSliceOpt();
480 try testSliceAlign();
481 try testConcatStrLiterals();
482 try testSliceLength();
483 try testSliceLengthZ();
484 try testArrayLength();
485 try testArrayLengthZ();
486 try testMultiPointer();
487 try testMultiPointerLengthZ();
488 try testSingleItemPointer();
489 }
490
491 fn testArray() !void {
492 var array = [5]u8{ 1, 2, 3, 4, 5 };
493 const slice = array[1..3];
494 comptime assert(@TypeOf(slice) == *[2]u8);
495 try expect(slice[0] == 2);
496 try expect(slice[1] == 3);
497 }
498
499 fn testArrayZ() !void {
500 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
501 comptime assert(@TypeOf(array[1..3]) == *[2]u8);
502 comptime assert(@TypeOf(array[1..5]) == *[4:0]u8);
503 comptime assert(@TypeOf(array[1..]) == *[4:0]u8);
504 comptime assert(@TypeOf(array[1..3 :4]) == *[2:4]u8);
505 }
506
507 fn testArray0() !void {
508 {
509 var array = [0]u8{};
510 const slice = array[0..0];
511 comptime assert(@TypeOf(slice) == *[0]u8);
512 }
513 {
514 var array = [0:0]u8{};
515 const slice = array[0..0];
516 comptime assert(@TypeOf(slice) == *[0:0]u8);
517 try expect(slice[0] == 0);
518 }
519 }
520
521 fn testArrayAlign() !void {
522 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
523 const slice = array[4..5];
524 comptime assert(@TypeOf(slice) == *align(4) [1]u8);
525 try expect(slice[0] == 5);
526 comptime assert(@TypeOf(array[0..2]) == *align(4) [2]u8);
527 }
528
529 fn testPointer() !void {
530 var array = [5]u8{ 1, 2, 3, 4, 5 };
531 var pointer: [*]u8 = &array;
532 const slice = pointer[1..3];
533 comptime assert(@TypeOf(slice) == *[2]u8);
534 try expect(slice[0] == 2);
535 try expect(slice[1] == 3);
536 }
537
538 fn testPointerZ() !void {
539 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
540 var pointer: [*:0]u8 = &array;
541 comptime assert(@TypeOf(pointer[1..3]) == *[2]u8);
542 comptime assert(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
543 }
544
545 fn testPointer0() !void {
546 var pointer: [*]const u0 = &[1]u0{0};
547 const slice = pointer[0..1];
548 comptime assert(@TypeOf(slice) == *const [1]u0);
549 try expect(slice[0] == 0);
550 }
551
552 fn testPointerAlign() !void {
553 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
554 var pointer: [*]align(4) u8 = &array;
555 const slice = pointer[4..5];
556 comptime assert(@TypeOf(slice) == *align(4) [1]u8);
557 try expect(slice[0] == 5);
558 comptime assert(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
559 }
560
561 fn testSlice() !void {
562 var array = [5]u8{ 1, 2, 3, 4, 5 };
563 var src_slice: []u8 = &array;
564 const slice = src_slice[1..3];
565 comptime assert(@TypeOf(slice) == *[2]u8);
566 try expect(slice[0] == 2);
567 try expect(slice[1] == 3);
568 }
569
570 fn testSliceZ() !void {
571 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
572 var slice: [:0]u8 = &array;
573 comptime assert(@TypeOf(slice[1..3]) == *[2]u8);
574 comptime assert(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
575 if (@inComptime()) {
576 comptime assert(@TypeOf(slice[1..]) == *[4:0]u8);
577 } else {
578 comptime assert(@TypeOf(slice[1..]) == [:0]u8);
579 }
580 }
581
582 fn testSliceOpt() !void {
583 var array: [2]u8 = [2]u8{ 1, 2 };
584 var slice: ?[]u8 = &array;
585 comptime assert(@TypeOf(&array, slice) == ?[]u8);
586 comptime assert(@TypeOf(slice, &array) == ?[]u8);
587 comptime assert(@TypeOf(slice.?[0..2]) == *[2]u8);
588 }
589
590 fn testSliceAlign() !void {
591 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
592 var src_slice: []align(4) u8 = &array;
593 const slice = src_slice[4..5];
594 comptime assert(@TypeOf(slice) == *align(4) [1]u8);
595 try expect(slice[0] == 5);
596 comptime assert(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
597 }
598
599 fn testConcatStrLiterals() !void {
600 try expectEqualSlices(u8, "ab", "a"[0..] ++ "b"[0..]);
601 try expectEqualSlices(u8, "ab", "a"[0.. :0] ++ "b"[0.. :0]);
602 }
603
604 fn testSliceLength() !void {
605 var array = [5]u8{ 1, 2, 3, 4, 5 };
606 var slice: []u8 = &array;
607 comptime assert(@TypeOf(slice[1..][0..2]) == *[2]u8);
608 comptime assert(@TypeOf(slice[1..][0..4]) == *[4]u8);
609 comptime assert(@TypeOf(slice[1..][0..2 :4]) == *[2:4]u8);
610 }
611
612 fn testSliceLengthZ() !void {
613 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
614 var slice: [:0]u8 = &array;
615 comptime assert(@TypeOf(slice[1..][0..2]) == *[2]u8);
616 comptime assert(@TypeOf(slice[1..][0..2 :4]) == *[2:4]u8);
617 comptime assert(@TypeOf(slice[1.. :0][0..2]) == *[2]u8);
618 comptime assert(@TypeOf(slice[1.. :0][0..2 :4]) == *[2:4]u8);
619 }
620
621 fn testArrayLength() !void {
622 var array = [5]u8{ 1, 2, 3, 4, 5 };
623 comptime assert(@TypeOf(array[1..][0..2]) == *[2]u8);
624 comptime assert(@TypeOf(array[1..][0..4]) == *[4]u8);
625 comptime assert(@TypeOf(array[1..][0..2 :4]) == *[2:4]u8);
626 }
627
628 fn testArrayLengthZ() !void {
629 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
630 comptime assert(@TypeOf(array[1..][0..2]) == *[2]u8);
631 comptime assert(@TypeOf(array[1..][0..4]) == *[4:0]u8);
632 comptime assert(@TypeOf(array[1..][0..2 :4]) == *[2:4]u8);
633 comptime assert(@TypeOf(array[1.. :0][0..2]) == *[2]u8);
634 comptime assert(@TypeOf(array[1.. :0][0..4]) == *[4:0]u8);
635 comptime assert(@TypeOf(array[1.. :0][0..2 :4]) == *[2:4]u8);
636 }
637
638 fn testMultiPointer() !void {
639 var array = [5]u8{ 1, 2, 3, 4, 5 };
640 var ptr: [*]u8 = &array;
641 comptime assert(@TypeOf(ptr[1..][0..2]) == *[2]u8);
642 comptime assert(@TypeOf(ptr[1..][0..4]) == *[4]u8);
643 comptime assert(@TypeOf(ptr[1..][0..2 :4]) == *[2:4]u8);
644 }
645
646 fn testMultiPointerLengthZ() !void {
647 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
648 var ptr: [*]u8 = &array;
649 comptime assert(@TypeOf(ptr[1..][0..2]) == *[2]u8);
650 comptime assert(@TypeOf(ptr[1..][0..4]) == *[4]u8);
651 comptime assert(@TypeOf(ptr[1..][0..2 :4]) == *[2:4]u8);
652
653 var ptr_z: [*:0]u8 = &array;
654 comptime assert(@TypeOf(ptr_z[1..][0..2]) == *[2]u8);
655 comptime assert(@TypeOf(ptr_z[1..][0..4]) == *[4]u8);
656 comptime assert(@TypeOf(ptr_z[1..][0..2 :4]) == *[2:4]u8);
657 comptime assert(@TypeOf(ptr_z[1.. :0][0..2]) == *[2]u8);
658 comptime assert(@TypeOf(ptr_z[1.. :0][0..4]) == *[4]u8);
659 comptime assert(@TypeOf(ptr_z[1.. :0][0..2 :4]) == *[2:4]u8);
660 }
661
662 fn testSingleItemPointer() !void {
663 var value: u8 = 1;
664 var ptr = &value;
665
666 const slice = ptr[0..1];
667 comptime assert(@TypeOf(slice) == *[1]u8);
668 try expect(slice[0] == 1);
669
670 comptime assert(@TypeOf(ptr[0..0]) == *[0]u8);
671 }
672 };
673
674 try S.doTheTest();
675 try comptime S.doTheTest();
676}
677
678test "slice pointer-to-array null terminated" {
679 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
680 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
681
682 comptime {
683 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
684 var slice: [:0]u8 = &array;
685 try expect(@TypeOf(slice[1..3]) == *[2]u8);
686 try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
687 try expect(@TypeOf(slice[1..]) == *[4:0]u8);
688 }
689
690 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
691 var slice: [:0]u8 = &array;
692 comptime assert(@TypeOf(slice[1..3]) == *[2]u8);
693 comptime assert(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
694 comptime assert(@TypeOf(slice[1..]) == [:0]u8);
695}
696
697test "slice pointer-to-array zero length" {
698 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
700
701 comptime {
702 {
703 var array = [0]u8{};
704 var src_slice: []u8 = &array;
705 const slice = src_slice[0..0];
706 try expect(@TypeOf(slice) == *[0]u8);
707 }
708 {
709 var array = [0:0]u8{};
710 var src_slice: [:0]u8 = &array;
711 const slice = src_slice[0..0];
712 try expect(@TypeOf(slice) == *[0:0]u8);
713 }
714 }
715
716 {
717 var array = [0]u8{};
718 var src_slice: []u8 = &array;
719 const slice = src_slice[0..0];
720 comptime assert(@TypeOf(slice) == *[0]u8);
721 }
722 {
723 var array = [0:0]u8{};
724 var src_slice: [:0]u8 = &array;
725 const slice = src_slice[0..0];
726 comptime assert(@TypeOf(slice) == *[0]u8);
727 }
728}
729
730test "type coercion of pointer to anon struct literal to pointer to slice" {
731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
733 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
734
735 const S = struct {
736 const U = union {
737 a: u32,
738 b: bool,
739 c: []const u8,
740 };
741
742 fn doTheTest() !void {
743 var x1: u8 = 42;
744 _ = &x1;
745 const t1 = &.{ x1, 56, 54 };
746 const slice1: []const u8 = t1;
747 try expect(slice1.len == 3);
748 try expect(slice1[0] == 42);
749 try expect(slice1[1] == 56);
750 try expect(slice1[2] == 54);
751
752 var x2: []const u8 = "hello";
753 _ = &x2;
754 const t2 = &.{ x2, ", ", "world!" };
755 // @compileLog(@TypeOf(t2));
756 const slice2: []const []const u8 = t2;
757 try expect(slice2.len == 3);
758 try expect(mem.eql(u8, slice2[0], "hello"));
759 try expect(mem.eql(u8, slice2[1], ", "));
760 try expect(mem.eql(u8, slice2[2], "world!"));
761 }
762 };
763 try S.doTheTest();
764 try comptime S.doTheTest();
765}
766
767test "array concat of slices gives ptr to array" {
768 comptime {
769 var a: []const u8 = "aoeu";
770 var b: []const u8 = "asdf";
771 _ = .{ &a, &b };
772 const c = a ++ b;
773 try expect(std.mem.eql(u8, c, "aoeuasdf"));
774 try expect(@TypeOf(c) == *const [8]u8);
775 }
776}
777
778test "slice bounds in comptime concatenation" {
779 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
780 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
781
782 const bs = comptime blk: {
783 const b = "........1........";
784 break :blk b[8..9];
785 };
786 const str = "" ++ bs;
787 try expect(str.len == 1);
788 try expect(std.mem.eql(u8, str, "1"));
789
790 const str2 = bs ++ "";
791 try expect(str2.len == 1);
792 try expect(std.mem.eql(u8, str2, "1"));
793}
794
795test "slice sentinel access at comptime" {
796 {
797 const str0 = &[_:0]u8{ '1', '2', '3' };
798 const slice0: [:0]const u8 = str0;
799
800 try expect(slice0.len == 3);
801 try expect(slice0[slice0.len] == 0);
802 }
803 {
804 const str0 = "123";
805 _ = &str0[0];
806 const slice0: [:0]const u8 = str0;
807
808 try expect(slice0.len == 3);
809 try expect(slice0[slice0.len] == 0);
810 }
811}
812
813test "slicing array with sentinel as end index" {
814 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
815 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
816 const S = struct {
817 fn do() !void {
818 var array = [_:0]u8{ 1, 2, 3, 4 };
819 const slice = array[4..5];
820 try expect(slice.len == 1);
821 try expect(slice[0] == 0);
822 try expect(@TypeOf(slice) == *[1]u8);
823 }
824 };
825
826 try S.do();
827 try comptime S.do();
828}
829
830test "slicing slice with sentinel as end index" {
831 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
832 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
833
834 const S = struct {
835 fn do() !void {
836 var array = [_:0]u8{ 1, 2, 3, 4 };
837 const src_slice: [:0]u8 = &array;
838 const slice = src_slice[4..5];
839 try expect(slice.len == 1);
840 try expect(slice[0] == 0);
841 try expect(@TypeOf(slice) == *[1]u8);
842 }
843 };
844
845 try S.do();
846 try comptime S.do();
847}
848
849test "slice len modification at comptime" {
850 comptime {
851 var buf: [10]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
852 var items: []u8 = buf[0..0];
853 items.len += 2;
854 try expect(items.len == 2);
855 try expect(items[0] == 0);
856 try expect(items[1] == 1);
857 }
858}
859
860test "slice field ptr const" {
861 const const_slice: []const u8 = "string";
862
863 const const_ptr_const_slice = &const_slice;
864 try expectEqual(*const []const u8, @TypeOf(&const_ptr_const_slice.*));
865 try expectEqual(*const [*]const u8, @TypeOf(&const_ptr_const_slice.ptr));
866
867 var var_ptr_const_slice = &const_slice;
868 try expectEqual(*const []const u8, @TypeOf(&var_ptr_const_slice.*));
869 try expectEqual(*const [*]const u8, @TypeOf(&var_ptr_const_slice.ptr));
870}
871
872test "slice field ptr var" {
873 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
874
875 var var_slice: []const u8 = "string";
876
877 var var_ptr_var_slice = &var_slice;
878 try expectEqual(*[]const u8, @TypeOf(&var_ptr_var_slice.*));
879 try expectEqual(*[*]const u8, @TypeOf(&var_ptr_var_slice.ptr));
880
881 const const_ptr_var_slice = &var_slice;
882 try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*));
883 try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr));
884}
885
886test "global slice field access" {
887 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
888 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
889 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
890 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
891
892 const S = struct {
893 var slice: []const u8 = undefined;
894 };
895 S.slice = "string";
896 S.slice.ptr += 1;
897 S.slice.len -= 2;
898 try expectEqualStrings("trin", S.slice);
899}
900
901test "slice of void" {
902 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
903
904 var n: usize = 10;
905 _ = &n;
906 var arr: [12]void = undefined;
907 const slice = @as([]void, &arr)[0..n];
908 try expect(slice.len == n);
909}
910
911test "slice with dereferenced value" {
912 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
913
914 var a: usize = 0;
915 const idx: *usize = &a;
916 _ = blk: {
917 var array = [_]u8{};
918 break :blk array[idx.*..];
919 };
920 const res = blk: {
921 var array = [_]u8{};
922 break :blk array[idx.*..];
923 };
924 try expect(res.len == 0);
925}
926
927test "empty slice ptr is non null" {
928 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Test assumes `undefined` is non-zero
929
930 {
931 const empty_slice: []u8 = &[_]u8{};
932 const p: [*]u8 = empty_slice.ptr + 0;
933 const t = @as([*]i8, @ptrCast(p));
934 try expect(@intFromPtr(t) == @intFromPtr(empty_slice.ptr));
935 }
936 {
937 const empty_slice: []u8 = &.{};
938 const p: [*]u8 = empty_slice.ptr + 0;
939 const t = @as([*]i8, @ptrCast(p));
940 try expect(@intFromPtr(t) == @intFromPtr(empty_slice.ptr));
941 }
942}
943
944test "slice decays to many pointer" {
945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
946 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
947
948 var buf: [8]u8 = "abcdefg\x00".*;
949 const p: [*:0]const u8 = buf[0..7 :0];
950 try expectEqualStrings(buf[0..7], std.mem.span(p));
951}
952
953test "write through pointer to optional slice arg" {
954 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
955 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
956 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
957
958 const S = struct {
959 fn bar(foo: *?[]const u8) !void {
960 foo.* = try baz();
961 }
962
963 fn baz() ![]const u8 {
964 return "ok";
965 }
966 };
967 var foo: ?[]const u8 = null;
968 try S.bar(&foo);
969 try expectEqualStrings(foo.?, "ok");
970}
971
972test "modify slice length at comptime" {
973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
974 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
975 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
976
977 const arr: [2]u8 = .{ 10, 20 };
978 comptime var s: []const u8 = arr[0..0];
979 s.len += 1;
980 const a = s;
981 s.len += 1;
982 const b = s;
983
984 try expectEqualSlices(u8, &.{10}, a);
985 try expectEqualSlices(u8, &.{ 10, 20 }, b);
986}
987
988test "slicing zero length array field of struct" {
989 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
990 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
991 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
992
993 const S = struct {
994 a: [0]usize,
995 fn foo(self: *@This(), start: usize, end: usize) []usize {
996 return self.a[start..end];
997 }
998 };
999 var s: S = undefined;
1000 try expect(s.foo(0, 0).len == 0);
1001}
1002
1003test "slicing slices gives correct result" {
1004 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1005 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1006
1007 const foo = "1234";
1008 const bar = foo[0..4];
1009 try expectEqualStrings("1234", bar);
1010 try expectEqualStrings("2", bar[1..2]);
1011 try expectEqualStrings("3", bar[2..3]);
1012 try expectEqualStrings("4", bar[3..4]);
1013 try expectEqualStrings("34", bar[2..4]);
1014}
1015
1016test "get address of element of zero-sized slice" {
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1018 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1019
1020 const S = struct {
1021 fn destroy(_: *void) void {}
1022 };
1023
1024 var slice: []void = undefined;
1025 S.destroy(&slice[0]);
1026}
1027
1028test "sentinel-terminated 0-length slices" {
1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1030 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1031
1032 const u32s: [4]u32 = [_]u32{ 0, 1, 2, 3 };
1033
1034 var index: u8 = 2;
1035 _ = &index;
1036 const slice = u32s[index..index :2];
1037 const array_ptr = u32s[2..2 :2];
1038 const comptime_known_array_value = u32s[2..2 :2].*;
1039 var runtime_array_value = u32s[2..2 :2].*;
1040 _ = &runtime_array_value;
1041
1042 try expect(slice[0] == 2);
1043 try expect(array_ptr[0] == 2);
1044 try expect(comptime_known_array_value[0] == 2);
1045 try expect(runtime_array_value[0] == 2);
1046}
1047
1048test "peer slices keep abi alignment with empty struct" {
1049 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1050
1051 var cond: bool = undefined;
1052 cond = false;
1053 const slice = if (cond) &[1]u32{42} else &.{};
1054 comptime assert(@TypeOf(slice) == []const u32);
1055 try expect(slice.len == 0);
1056}
1057
1058test "sentinel expression in slice operation has result type" {
1059 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1060
1061 const sentinel = std.math.maxInt(u16);
1062
1063 const arr: [3]u16 = .{ 1, 2, sentinel };
1064 const slice = arr[0..2 :@intCast(sentinel)];
1065
1066 comptime assert(@TypeOf(slice) == *const [2:sentinel]u16);
1067 comptime assert(slice[2] == sentinel);
1068 comptime assert(slice.len == 2);
1069 comptime assert(slice[0] == 1);
1070 comptime assert(slice[1] == 2);
1071}
1072
1073test "conditionally return second argument slice" {
1074 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1075
1076 const S = struct {
1077 fn foo(cond: bool, slice: []const u8) []const u8 {
1078 if (cond) return slice;
1079 return &.{};
1080 }
1081 };
1082
1083 try expectEqualStrings("", S.foo(false, "false"));
1084 try expectEqualStrings("true", S.foo(true, "true"));
1085}
1086
1087test "slice field alignment" {
1088 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1089
1090 const S = struct {
1091 fn doTheTest(p: *align(1) const []u8) !void {
1092 comptime assert(@TypeOf(&p.ptr) == *align(1) const [*]u8);
1093 comptime assert(@TypeOf(&p.len) == *align(1) const usize);
1094 try expect(p.len == 10);
1095 }
1096 };
1097 var arr: [10]u8 = @splat(0);
1098 try S.doTheTest(&&arr);
1099}
1100
1101test "directly deref slice with comptime-known length" {
1102 {
1103 const slice: []const u16 = &.{ 1, 2, 3 };
1104 const array = slice.*;
1105
1106 comptime assert(@TypeOf(array) == [3]u16);
1107 comptime assert(array[0] == 1);
1108 comptime assert(array[1] == 2);
1109 comptime assert(array[2] == 3);
1110 }
1111 {
1112 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1113 const array = slice.*;
1114
1115 comptime assert(@TypeOf(array) == [3:0]u16);
1116 comptime assert(array[0] == 1);
1117 comptime assert(array[1] == 2);
1118 comptime assert(array[2] == 3);
1119 comptime assert(array[3] == 0);
1120 }
1121}
1122
1123test "address of dereferenced slice is array pointer" {
1124 {
1125 const slice: []const u16 = &.{ 1, 2, 3 };
1126 const array_ptr = &slice.*;
1127
1128 comptime assert(@TypeOf(array_ptr) == *const [3]u16);
1129 comptime assert(array_ptr[0] == 1);
1130 comptime assert(array_ptr[1] == 2);
1131 comptime assert(array_ptr[2] == 3);
1132 }
1133 {
1134 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1135 const array_ptr = &slice.*;
1136
1137 comptime assert(@TypeOf(array_ptr) == *const [3:0]u16);
1138 comptime assert(array_ptr[0] == 1);
1139 comptime assert(array_ptr[1] == 2);
1140 comptime assert(array_ptr[2] == 3);
1141 comptime assert(array_ptr[3] == 0);
1142 }
1143}
1144
1145test "coerce slice with comptime-known length to array pointer" {
1146 {
1147 const slice: []const u16 = &.{ 1, 2, 3 };
1148 const array_ptr: *const [3]u16 = slice;
1149
1150 comptime assert(array_ptr[0] == 1);
1151 comptime assert(array_ptr[1] == 2);
1152 comptime assert(array_ptr[2] == 3);
1153 }
1154 {
1155 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1156 const array_ptr: *const [3:0]u16 = slice;
1157
1158 comptime assert(array_ptr[0] == 1);
1159 comptime assert(array_ptr[1] == 2);
1160 comptime assert(array_ptr[2] == 3);
1161 comptime assert(array_ptr[3] == 0);
1162 }
1163 {
1164 const slice: [:0]const u16 = &.{ 1, 2, 3 };
1165 const array_ptr: *const [3]u16 = slice;
1166
1167 comptime assert(array_ptr[0] == 1);
1168 comptime assert(array_ptr[1] == 2);
1169 comptime assert(array_ptr[2] == 3);
1170 }
1171}
1172
1173test "modify slice through coerced array pointer" {
1174 comptime {
1175 var array: [3]u16 = .{ 1, 2, 3 };
1176 const slice: []u16 = &array;
1177 const array_ptr: *[3]u16 = slice;
1178 array_ptr[2] = 0;
1179 assert(slice[2] == 0);
1180 }
1181}