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}