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