master
  1const builtin = @import("builtin");
  2const std = @import("std");
  3const expect = std.testing.expect;
  4const expectEqual = std.testing.expectEqual;
  5const mem = std.mem;
  6
  7test "continue in for loop" {
  8    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
  9
 10    const array = [_]i32{ 1, 2, 3, 4, 5 };
 11    var sum: i32 = 0;
 12    for (array) |x| {
 13        sum += x;
 14        if (x < 3) {
 15            continue;
 16        }
 17        break;
 18    }
 19    if (sum != 6) unreachable;
 20}
 21
 22test "break from outer for loop" {
 23    try testBreakOuter();
 24    try comptime testBreakOuter();
 25}
 26
 27fn testBreakOuter() !void {
 28    const array = "aoeu";
 29    var count: usize = 0;
 30    outer: for (array) |_| {
 31        for (array) |_| {
 32            count += 1;
 33            break :outer;
 34        }
 35    }
 36    try expect(count == 1);
 37}
 38
 39test "continue outer for loop" {
 40    try testContinueOuter();
 41    try comptime testContinueOuter();
 42}
 43
 44fn testContinueOuter() !void {
 45    const array = "aoeu";
 46    var counter: usize = 0;
 47    outer: for (array) |_| {
 48        for (array) |_| {
 49            counter += 1;
 50            continue :outer;
 51        }
 52    }
 53    try expect(counter == array.len);
 54}
 55
 56test "ignore lval with underscore (for loop)" {
 57    for ([_]void{}, 0..) |_, i| {
 58        _ = i;
 59        for ([_]void{}, 0..) |_, j| {
 60            _ = j;
 61            break;
 62        }
 63        break;
 64    }
 65}
 66
 67test "basic for loop" {
 68    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
 69    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 70    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
 71
 72    const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
 73
 74    var buffer: [expected_result.len]u8 = undefined;
 75    var buf_index: usize = 0;
 76
 77    const array = [_]u8{ 9, 8, 7, 6 };
 78    for (array) |item| {
 79        buffer[buf_index] = item;
 80        buf_index += 1;
 81    }
 82    for (array, 0..) |item, index| {
 83        _ = item;
 84        buffer[buf_index] = @as(u8, @intCast(index));
 85        buf_index += 1;
 86    }
 87    const array_ptr = &array;
 88    for (array_ptr) |item| {
 89        buffer[buf_index] = item;
 90        buf_index += 1;
 91    }
 92    for (array_ptr, 0..) |item, index| {
 93        _ = item;
 94        buffer[buf_index] = @as(u8, @intCast(index));
 95        buf_index += 1;
 96    }
 97    const unknown_size: []const u8 = &array;
 98    for (unknown_size) |item| {
 99        buffer[buf_index] = item;
100        buf_index += 1;
101    }
102    for (unknown_size, 0..) |_, index| {
103        buffer[buf_index] = @as(u8, @intCast(index));
104        buf_index += 1;
105    }
106
107    try expect(mem.eql(u8, buffer[0..buf_index], &expected_result));
108}
109
110test "for with null and T peer types and inferred result location type" {
111    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
112    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
113    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
114
115    const S = struct {
116        fn doTheTest(slice: []const u8) !void {
117            if (for (slice) |item| {
118                if (item == 10) {
119                    break item;
120                }
121            } else null) |v| {
122                _ = v;
123                @panic("fail");
124            }
125        }
126    };
127    try S.doTheTest(&[_]u8{ 1, 2 });
128    try comptime S.doTheTest(&[_]u8{ 1, 2 });
129}
130
131test "2 break statements and an else" {
132    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
133
134    const S = struct {
135        fn entry(t: bool, f: bool) !void {
136            var buf: [10]u8 = undefined;
137            var ok = false;
138            ok = for (&buf) |*item| {
139                _ = item;
140                if (f) break false;
141                if (t) break true;
142            } else false;
143            try expect(ok);
144        }
145    };
146    try S.entry(true, false);
147    try comptime S.entry(true, false);
148}
149
150test "for loop with pointer elem var" {
151    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
152    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
153    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
154
155    const source = "abcdefg";
156    var target: [source.len]u8 = undefined;
157    @memcpy(target[0..], source);
158    mangleString(target[0..]);
159    try expect(mem.eql(u8, &target, "bcdefgh"));
160
161    for (source, 0..) |*c, i| {
162        _ = i;
163        try expect(@TypeOf(c) == *const u8);
164    }
165    for (&target, 0..) |*c, i| {
166        _ = i;
167        try expect(@TypeOf(c) == *u8);
168    }
169}
170
171fn mangleString(s: []u8) void {
172    for (s) |*c| {
173        c.* += 1;
174    }
175}
176
177test "for copies its payload" {
178    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179
180    const S = struct {
181        fn doTheTest() !void {
182            var x = [_]usize{ 1, 2, 3 };
183            for (x, 0..) |value, i| {
184                // Modify the original array
185                x[i] += 99;
186                try expect(value == i + 1);
187            }
188        }
189    };
190    try S.doTheTest();
191    try comptime S.doTheTest();
192}
193
194test "for on slice with allowzero ptr" {
195    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
196    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
197    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
198
199    const S = struct {
200        fn doTheTest(slice: []const u8) !void {
201            const ptr = @as([*]allowzero const u8, @ptrCast(slice.ptr))[0..slice.len];
202            for (ptr, 0..) |x, i| try expect(x == i + 1);
203            for (ptr, 0..) |*x, i| try expect(x.* == i + 1);
204        }
205    };
206    try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
207    try comptime S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
208}
209
210test "else continue outer for" {
211    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
212    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
213
214    var i: usize = 6;
215    var buf: [5]u8 = undefined;
216    while (true) {
217        i -= 1;
218        for (buf[i..5]) |_| {
219            return;
220        } else continue;
221    }
222}
223
224test "for loop with else branch" {
225    {
226        var x = [_]u32{ 1, 2 };
227        _ = &x;
228        const q = for (x) |y| {
229            if ((y & 1) != 0) continue;
230            break y * 2;
231        } else @as(u32, 1);
232        try expect(q == 4);
233    }
234    {
235        var x = [_]u32{ 1, 2 };
236        _ = &x;
237        const q = for (x) |y| {
238            if ((y & 1) != 0) continue;
239            break y * 2;
240        } else @panic("");
241        try expect(q == 4);
242    }
243}
244
245test "count over fixed range" {
246    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
247    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
248
249    var sum: usize = 0;
250    for (0..6) |i| {
251        sum += i;
252    }
253
254    try expect(sum == 15);
255}
256
257test "two counters" {
258    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
259    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
260
261    var sum: usize = 0;
262    for (0..10, 10..20) |i, j| {
263        sum += 1;
264        try expect(i + 10 == j);
265    }
266
267    try expect(sum == 10);
268}
269
270test "1-based counter and ptr to array" {
271    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
272    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
273
274    var ok: usize = 0;
275
276    for (1..6, "hello") |i, b| {
277        if (i == 1) {
278            try expect(b == 'h');
279            ok += 1;
280        }
281        if (i == 2) {
282            try expect(b == 'e');
283            ok += 1;
284        }
285        if (i == 3) {
286            try expect(b == 'l');
287            ok += 1;
288        }
289        if (i == 4) {
290            try expect(b == 'l');
291            ok += 1;
292        }
293        if (i == 5) {
294            try expect(b == 'o');
295            ok += 1;
296        }
297    }
298
299    try expect(ok == 5);
300}
301
302test "slice and two counters, one is offset and one is runtime" {
303    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
304    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
305    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
306
307    const slice: []const u8 = "blah";
308    var start: usize = 0;
309    _ = &start;
310
311    for (slice, start..4, 1..5) |a, b, c| {
312        if (a == 'b') {
313            try expect(b == 0);
314            try expect(c == 1);
315        }
316        if (a == 'l') {
317            try expect(b == 1);
318            try expect(c == 2);
319        }
320        if (a == 'a') {
321            try expect(b == 2);
322            try expect(c == 3);
323        }
324        if (a == 'h') {
325            try expect(b == 3);
326            try expect(c == 4);
327        }
328    }
329}
330
331test "two slices, one captured by-ref" {
332    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
333    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
334    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
335
336    var buf: [10]u8 = undefined;
337    const slice1: []const u8 = "blah";
338    const slice2: []u8 = buf[0..4];
339
340    for (slice1, slice2) |a, *b| {
341        b.* = a;
342    }
343
344    try expect(slice2[0] == 'b');
345    try expect(slice2[1] == 'l');
346    try expect(slice2[2] == 'a');
347    try expect(slice2[3] == 'h');
348}
349
350test "raw pointer and slice" {
351    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
352    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
353    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
354
355    var buf: [10]u8 = undefined;
356    const slice: []const u8 = "blah";
357    const ptr: [*]u8 = buf[0..4];
358
359    for (ptr, slice) |*a, b| {
360        a.* = b;
361    }
362
363    try expect(buf[0] == 'b');
364    try expect(buf[1] == 'l');
365    try expect(buf[2] == 'a');
366    try expect(buf[3] == 'h');
367}
368
369test "raw pointer and counter" {
370    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
371    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
372    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
373
374    var buf: [10]u8 = undefined;
375    const ptr: [*]u8 = &buf;
376
377    for (ptr, 0..4) |*a, b| {
378        a.* = @as(u8, @intCast('A' + b));
379    }
380
381    try expect(buf[0] == 'A');
382    try expect(buf[1] == 'B');
383    try expect(buf[2] == 'C');
384    try expect(buf[3] == 'D');
385}
386
387test "inline for with slice as the comptime-known" {
388    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
389    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
390
391    const comptime_slice = "hello";
392    var runtime_i: usize = 3;
393    _ = &runtime_i;
394
395    const S = struct {
396        var ok: usize = 0;
397        fn check(comptime a: u8, b: usize) !void {
398            if (a == 'l') {
399                try expect(b == 3);
400                ok += 1;
401            } else if (a == 'o') {
402                try expect(b == 4);
403                ok += 1;
404            } else {
405                @compileError("fail");
406            }
407        }
408    };
409
410    inline for (comptime_slice[3..5], runtime_i..5) |a, b| {
411        try S.check(a, b);
412    }
413
414    try expect(S.ok == 2);
415}
416
417test "inline for with counter as the comptime-known" {
418    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
419    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
420    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
421
422    var runtime_slice = "hello";
423    var runtime_i: usize = 3;
424    _ = &runtime_i;
425
426    const S = struct {
427        var ok: usize = 0;
428        fn check(a: u8, comptime b: usize) !void {
429            if (b == 3) {
430                try expect(a == 'l');
431                ok += 1;
432            } else if (b == 4) {
433                try expect(a == 'o');
434                ok += 1;
435            } else {
436                @compileError("fail");
437            }
438        }
439    };
440
441    inline for (runtime_slice[runtime_i..5], 3..5) |a, b| {
442        try S.check(a, b);
443    }
444
445    try expect(S.ok == 2);
446}
447
448test "inline for on tuple pointer" {
449    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
450    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
451    if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
452
453    const S = struct { u32, u32, u32 };
454    var s: S = .{ 100, 200, 300 };
455
456    inline for (&s, 0..) |*x, i| {
457        x.* = i;
458    }
459
460    try expectEqual(S{ 0, 1, 2 }, s);
461}
462
463test "ref counter that starts at zero" {
464    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
465    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
466
467    for ([_]usize{ 0, 1, 2 }, 0..) |i, j| {
468        try expectEqual(i, j);
469        try expectEqual((&i).*, (&j).*);
470    }
471    inline for (.{ 0, 1, 2 }, 0..) |i, j| {
472        try expectEqual(i, j);
473        try expectEqual((&i).*, (&j).*);
474    }
475}
476
477test "inferred alloc ptr of for loop" {
478    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
479    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
480
481    {
482        var cond = false;
483        _ = &cond;
484        const opt = for (0..1) |_| {
485            if (cond) break cond;
486        } else null;
487        try expectEqual(@as(?bool, null), opt);
488    }
489    {
490        var cond = true;
491        _ = &cond;
492        const opt = for (0..1) |_| {
493            if (cond) break cond;
494        } else null;
495        try expectEqual(@as(?bool, true), opt);
496    }
497}
498
499test "for loop results in a bool" {
500    if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501
502    try std.testing.expect(for ([1]u8{0}) |x| {
503        if (x == 0) break true;
504    } else false);
505}
506
507test "return from inline for" {
508    const S = struct {
509        fn do() bool {
510            inline for (.{"a"}) |_| {
511                if (true) return false;
512            }
513            return true;
514        }
515    };
516    try std.testing.expect(!S.do());
517}
518
519test "for loop 0 length range" {
520    const map: []const u8 = &.{};
521    for (map, 0..map.len) |i, j| {
522        _ = i;
523        _ = j;
524        comptime unreachable;
525    }
526}