master
1const builtin = @import("builtin");
2const std = @import("std");
3const assert = std.debug.assert;
4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;
6
7test "compile time recursion" {
8 try expect(some_data.len == 21);
9}
10var some_data: [@as(usize, @intCast(fibonacci(7)))]u8 = undefined;
11fn fibonacci(x: i32) i32 {
12 if (x <= 1) return 1;
13 return fibonacci(x - 1) + fibonacci(x - 2);
14}
15
16fn unwrapAndAddOne(blah: ?i32) i32 {
17 return blah.? + 1;
18}
19const should_be_1235 = unwrapAndAddOne(1234);
20test "static add one" {
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23
24 try expect(should_be_1235 == 1235);
25}
26
27test "inlined loop" {
28 comptime var i = 0;
29 comptime var sum = 0;
30 inline while (i <= 5) : (i += 1)
31 sum += i;
32 try expect(sum == 15);
33}
34
35fn gimme1or2(comptime a: bool) i32 {
36 const x: i32 = 1;
37 const y: i32 = 2;
38 comptime var z: i32 = if (a) x else y;
39 _ = &z;
40 return z;
41}
42test "inline variable gets result of const if" {
43 try expect(gimme1or2(true) == 1);
44 try expect(gimme1or2(false) == 2);
45}
46
47test "static function evaluation" {
48 try expect(statically_added_number == 3);
49}
50const statically_added_number = staticAdd(1, 2);
51fn staticAdd(a: i32, b: i32) i32 {
52 return a + b;
53}
54
55test "const expr eval on single expr blocks" {
56 try expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
57 comptime assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
58}
59
60fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
61 const literal = 3;
62
63 const result = if (b) b: {
64 break :b literal;
65 } else b: {
66 break :b x;
67 };
68
69 return result;
70}
71
72test "constant expressions" {
73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
74
75 var array: [array_size]u8 = undefined;
76 _ = &array;
77 try expect(@sizeOf(@TypeOf(array)) == 20);
78}
79const array_size: u8 = 20;
80
81fn max(comptime T: type, a: T, b: T) T {
82 if (T == bool) {
83 return a or b;
84 } else if (a > b) {
85 return a;
86 } else {
87 return b;
88 }
89}
90fn letsTryToCompareBools(a: bool, b: bool) bool {
91 return max(bool, a, b);
92}
93test "inlined block and runtime block phi" {
94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
95
96 try expect(letsTryToCompareBools(true, true));
97 try expect(letsTryToCompareBools(true, false));
98 try expect(letsTryToCompareBools(false, true));
99 try expect(!letsTryToCompareBools(false, false));
100
101 comptime {
102 try expect(letsTryToCompareBools(true, true));
103 try expect(letsTryToCompareBools(true, false));
104 try expect(letsTryToCompareBools(false, true));
105 try expect(!letsTryToCompareBools(false, false));
106 }
107}
108
109test "eval @setRuntimeSafety at compile-time" {
110 const result = comptime fnWithSetRuntimeSafety();
111 try expect(result == 1234);
112}
113
114fn fnWithSetRuntimeSafety() i32 {
115 @setRuntimeSafety(true);
116 return 1234;
117}
118
119test "compile-time downcast when the bits fit" {
120 comptime {
121 const spartan_count: u16 = 255;
122 const byte = @as(u8, @intCast(spartan_count));
123 try expect(byte == 255);
124 }
125}
126
127test "pointer to type" {
128 comptime {
129 var T: type = i32;
130 try expect(T == i32);
131 const ptr = &T;
132 try expect(@TypeOf(ptr) == *type);
133 ptr.* = f32;
134 try expect(T == f32);
135 try expect(*T == *f32);
136 }
137}
138
139test "a type constructed in a global expression" {
140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
143
144 var l: List = undefined;
145 l.array[0] = 10;
146 l.array[1] = 11;
147 l.array[2] = 12;
148 const ptr = @as([*]u8, @ptrCast(&l.array));
149 try expect(ptr[0] == 10);
150 try expect(ptr[1] == 11);
151 try expect(ptr[2] == 12);
152}
153
154const List = blk: {
155 const T = [10]u8;
156 break :blk struct {
157 array: T,
158 };
159};
160
161test "comptime function with the same args is memoized" {
162 comptime {
163 try expect(MakeType(i32) == MakeType(i32));
164 try expect(MakeType(i32) != MakeType(f64));
165 }
166}
167
168fn MakeType(comptime T: type) type {
169 return struct {
170 field: T,
171 };
172}
173
174test "try to trick eval with runtime if" {
175 try expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
176}
177
178fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
179 comptime var i: usize = 0;
180 inline while (i < 10) : (i += 1) {
181 const result = if (b) false else true;
182 _ = result;
183 }
184 return comptime i;
185}
186
187test "@setEvalBranchQuota" {
188 comptime {
189 // 1001 for the loop and then 1 more for the expect fn call
190 @setEvalBranchQuota(1002);
191 var i = 0;
192 var sum = 0;
193 while (i < 1001) : (i += 1) {
194 sum += i;
195 }
196 try expect(sum == 500500);
197 }
198}
199
200test "constant struct with negation" {
201 try expect(vertices[0].x == @as(f32, -0.6));
202}
203const Vertex = struct {
204 x: f32,
205 y: f32,
206 r: f32,
207 g: f32,
208 b: f32,
209};
210const vertices = [_]Vertex{
211 Vertex{
212 .x = -0.6,
213 .y = -0.4,
214 .r = 1.0,
215 .g = 0.0,
216 .b = 0.0,
217 },
218 Vertex{
219 .x = 0.6,
220 .y = -0.4,
221 .r = 0.0,
222 .g = 1.0,
223 .b = 0.0,
224 },
225 Vertex{
226 .x = 0.0,
227 .y = 0.6,
228 .r = 0.0,
229 .g = 0.0,
230 .b = 1.0,
231 },
232};
233
234test "statically initialized list" {
235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
236
237 try expect(static_point_list[0].x == 1);
238 try expect(static_point_list[0].y == 2);
239 try expect(static_point_list[1].x == 3);
240 try expect(static_point_list[1].y == 4);
241}
242const Point = struct {
243 x: i32,
244 y: i32,
245};
246const static_point_list = [_]Point{
247 makePoint(1, 2),
248 makePoint(3, 4),
249};
250fn makePoint(x: i32, y: i32) Point {
251 return Point{
252 .x = x,
253 .y = y,
254 };
255}
256
257test "statically initialized array literal" {
258 const y: [4]u8 = st_init_arr_lit_x;
259 try expect(y[3] == 4);
260}
261const st_init_arr_lit_x = [_]u8{ 1, 2, 3, 4 };
262
263const CmdFn = struct {
264 name: []const u8,
265 func: fn (i32) i32,
266};
267
268const cmd_fns = [_]CmdFn{
269 CmdFn{
270 .name = "one",
271 .func = one,
272 },
273 CmdFn{
274 .name = "two",
275 .func = two,
276 },
277 CmdFn{
278 .name = "three",
279 .func = three,
280 },
281};
282fn one(value: i32) i32 {
283 return value + 1;
284}
285fn two(value: i32) i32 {
286 return value + 2;
287}
288fn three(value: i32) i32 {
289 return value + 3;
290}
291
292fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
293 var result: i32 = start_value;
294 comptime var i = 0;
295 inline while (i < cmd_fns.len) : (i += 1) {
296 if (cmd_fns[i].name[0] == prefix_char) {
297 result = cmd_fns[i].func(result);
298 }
299 }
300 return result;
301}
302
303test "comptime iterate over fn ptr list" {
304 try expect(performFn('t', 1) == 6);
305 try expect(performFn('o', 0) == 1);
306 try expect(performFn('w', 99) == 99);
307}
308
309test "create global array with for loop" {
310 try expect(global_array[5] == 5 * 5);
311 try expect(global_array[9] == 9 * 9);
312}
313
314const global_array = x: {
315 var result: [10]usize = undefined;
316 for (&result, 0..) |*item, index| {
317 item.* = index * index;
318 }
319 break :x result;
320};
321
322fn generateTable(comptime T: type) [1010]T {
323 var res: [1010]T = undefined;
324 var i: usize = 0;
325 while (i < 1010) : (i += 1) {
326 res[i] = @as(T, @intCast(i));
327 }
328 return res;
329}
330
331fn doesAlotT(comptime T: type, value: usize) T {
332 @setEvalBranchQuota(5000);
333 const table = comptime blk: {
334 break :blk generateTable(T);
335 };
336 return table[value];
337}
338
339test "@setEvalBranchQuota at same scope as generic function call" {
340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
341
342 try expect(doesAlotT(u32, 2) == 2);
343}
344
345pub const Info = struct {
346 version: u8,
347};
348
349pub const diamond_info = Info{ .version = 0 };
350
351test "comptime modification of const struct field" {
352 comptime {
353 var res = diamond_info;
354 res.version = 1;
355 try expect(diamond_info.version == 0);
356 try expect(res.version == 1);
357 }
358}
359
360test "refer to the type of a generic function" {
361 const Func = fn (comptime type) void;
362 const f: Func = doNothingWithType;
363 f(i32);
364}
365
366fn doNothingWithType(comptime T: type) void {
367 _ = T;
368}
369
370test "zero extend from u0 to u1" {
371 var zero_u0: u0 = 0;
372 var zero_u1: u1 = zero_u0;
373 _ = .{ &zero_u0, &zero_u1 };
374 try expect(zero_u1 == 0);
375}
376
377test "return 0 from function that has u0 return type" {
378 const S = struct {
379 fn foo_zero() u0 {
380 return 0;
381 }
382 };
383 comptime {
384 if (S.foo_zero() != 0) {
385 @compileError("test failed");
386 }
387 }
388}
389
390test "statically initialized struct" {
391 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
392
393 st_init_str_foo.x += 1;
394 try expect(st_init_str_foo.x == 14);
395}
396const StInitStrFoo = struct {
397 x: i32,
398 y: bool,
399};
400var st_init_str_foo = StInitStrFoo{
401 .x = 13,
402 .y = true,
403};
404
405test "inline for with same type but different values" {
406 var res: usize = 0;
407 inline for ([_]type{ [2]u8, [1]u8, [2]u8 }) |T| {
408 var a: T = undefined;
409 _ = &a;
410 res += a.len;
411 }
412 try expect(res == 5);
413}
414
415test "f32 at compile time is lossy" {
416 try expect(@as(f32, 1 << 24) + 1 == 1 << 24);
417}
418
419test "f64 at compile time is lossy" {
420 try expect(@as(f64, 1 << 53) + 1 == 1 << 53);
421}
422
423test {
424 comptime assert(@as(f128, 1 << 113) == 10384593717069655257060992658440192);
425}
426
427fn copyWithPartialInline(s: []u32, b: []u8) void {
428 comptime var i: usize = 0;
429 inline while (i < 4) : (i += 1) {
430 s[i] = 0;
431 s[i] |= @as(u32, b[i * 4 + 0]) << 24;
432 s[i] |= @as(u32, b[i * 4 + 1]) << 16;
433 s[i] |= @as(u32, b[i * 4 + 2]) << 8;
434 s[i] |= @as(u32, b[i * 4 + 3]) << 0;
435 }
436}
437
438test "binary math operator in partially inlined function" {
439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
442
443 var s: [4]u32 = undefined;
444 var b: [16]u8 = undefined;
445
446 for (&b, 0..) |*r, i|
447 r.* = @as(u8, @intCast(i + 1));
448
449 copyWithPartialInline(s[0..], b[0..]);
450 try expect(s[0] == 0x1020304);
451 try expect(s[1] == 0x5060708);
452 try expect(s[2] == 0x90a0b0c);
453 try expect(s[3] == 0xd0e0f10);
454}
455
456test "comptime shl" {
457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
460
461 const a: u128 = 3;
462 const b: u7 = 63;
463 const c: u128 = 3 << 63;
464 try expect((a << b) == c);
465}
466
467test "comptime bitwise operators" {
468 comptime {
469 try expect(3 & 1 == 1);
470 try expect(3 & -1 == 3);
471 try expect(-3 & -1 == -3);
472 try expect(3 | -1 == -1);
473 try expect(-3 | -1 == -1);
474 try expect(3 ^ -1 == -4);
475 try expect(-3 ^ -1 == 2);
476 try expect(~@as(i8, -1) == 0);
477 try expect(~@as(i128, -1) == 0);
478 try expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
479 try expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
480 try expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff);
481 }
482}
483
484test "comptime shlWithOverflow" {
485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
487 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
488
489 const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0];
490 var a = ~@as(u64, 0);
491 _ = &a;
492 const rt_shifted = @shlWithOverflow(a, 16)[0];
493
494 try expect(ct_shifted == rt_shifted);
495}
496
497test "const ptr to variable data changes at runtime" {
498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
500
501 try expect(foo_ref.name[0] == 'a');
502 foo_ref.name = "b";
503 try expect(foo_ref.name[0] == 'b');
504}
505
506const Foo = struct {
507 name: []const u8,
508};
509
510var foo_contents = Foo{ .name = "a" };
511const foo_ref = &foo_contents;
512
513test "runtime 128 bit integer division" {
514 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
518 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
519 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
520
521 var a: u128 = 152313999999999991610955792383;
522 var b: u128 = 10000000000000000000;
523 _ = .{ &a, &b };
524 const c = a / b;
525 try expect(c == 15231399999);
526}
527
528test "@tagName of @typeInfo" {
529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
530 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
531
532 const str = @tagName(@typeInfo(u8));
533 try expect(std.mem.eql(u8, str, "int"));
534}
535
536test "static eval list init" {
537 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
539
540 try expect(static_vec3.data[2] == 1.0);
541 try expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
542}
543const static_vec3 = vec3(0.0, 0.0, 1.0);
544pub const Vec3 = struct {
545 data: [3]f32,
546};
547pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
548 return Vec3{
549 .data = [_]f32{ x, y, z },
550 };
551}
552
553test "inlined loop has array literal with elided runtime scope on first iteration but not second iteration" {
554 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
555
556 var runtime = [1]i32{3};
557 _ = &runtime;
558 comptime var i: usize = 0;
559 inline while (i < 2) : (i += 1) {
560 const result = if (i == 0) [1]i32{2} else runtime;
561 _ = result;
562 }
563 comptime {
564 try expect(i == 2);
565 }
566}
567
568test "ptr to local array argument at comptime" {
569 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
570
571 comptime {
572 var bytes: [10]u8 = undefined;
573 modifySomeBytes(bytes[0..]);
574 try expect(bytes[0] == 'a');
575 try expect(bytes[9] == 'b');
576 }
577}
578
579fn modifySomeBytes(bytes: []u8) void {
580 bytes[0] = 'a';
581 bytes[9] = 'b';
582}
583
584test "comparisons 0 <= uint and 0 > uint should be comptime" {
585 testCompTimeUIntComparisons(1234);
586}
587fn testCompTimeUIntComparisons(x: u32) void {
588 if (!(0 <= x)) {
589 @compileError("this condition should be comptime-known");
590 }
591 if (0 > x) {
592 @compileError("this condition should be comptime-known");
593 }
594 if (!(x >= 0)) {
595 @compileError("this condition should be comptime-known");
596 }
597 if (x < 0) {
598 @compileError("this condition should be comptime-known");
599 }
600}
601
602const hi1 = "hi";
603const hi2 = hi1;
604test "const global shares pointer with other same one" {
605 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
606 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
607
608 try assertEqualPtrs(&hi1[0], &hi2[0]);
609 comptime assert(&hi1[0] == &hi2[0]);
610}
611fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) !void {
612 try expect(ptr1 == ptr2);
613}
614
615// This one is still up for debate in the language specification.
616// Application code should not rely on this behavior until it is solidified.
617// Historically, stage1 had special case code to make this pass for string literals
618// but it did not work if the values are constructed with comptime code, or if
619// arrays of non-u8 elements are used instead.
620// The official language specification might not make this guarantee. However, if
621// it does make this guarantee, it will make it consistently for all types, not
622// only string literals. This is why Zig currently has a string table for
623// string literals, to match legacy stage1 behavior and pass this test, however
624// the end-game once the lang spec issue is settled would be to use a global
625// InternPool for comptime memoized objects, making this behavior consistent
626// across all types.
627test "string literal used as comptime slice is memoized" {
628 const a = "link";
629 const b = "link";
630 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
631 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
632}
633
634pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
635 _ = field_name;
636 return struct {
637 pub const Node = struct {};
638 };
639}
640
641test "comptime function with mutable pointer is not memoized" {
642 comptime {
643 var x: i32 = 1;
644 const ptr = &x;
645 increment(ptr);
646 increment(ptr);
647 try expect(x == 3);
648 }
649}
650
651fn increment(value: *i32) void {
652 value.* += 1;
653}
654
655test "const ptr to comptime mutable data is not memoized" {
656 comptime {
657 var foo = SingleFieldStruct{ .x = 1 };
658 try expect(foo.read_x() == 1);
659 foo.x = 2;
660 try expect(foo.read_x() == 2);
661 }
662}
663
664const SingleFieldStruct = struct {
665 x: i32,
666
667 fn read_x(self: *const SingleFieldStruct) i32 {
668 return self.x;
669 }
670};
671
672test "function which returns struct with type field causes implicit comptime" {
673 const ty = wrap(i32).T;
674 try expect(ty == i32);
675}
676
677const Wrapper = struct {
678 T: type,
679};
680
681fn wrap(comptime T: type) Wrapper {
682 return Wrapper{ .T = T };
683}
684
685test "call method with comptime pass-by-non-copying-value self parameter" {
686 const S = struct {
687 a: u8,
688
689 fn b(comptime s: @This()) u8 {
690 return s.a;
691 }
692 };
693
694 const s = S{ .a = 2 };
695 const b = s.b();
696 try expect(b == 2);
697}
698
699test "setting backward branch quota just before a generic fn call" {
700 @setEvalBranchQuota(1001);
701 loopNTimes(1001);
702}
703
704fn loopNTimes(comptime n: usize) void {
705 comptime var i = 0;
706 inline while (i < n) : (i += 1) {}
707}
708
709test "variable inside inline loop that has different types on different iterations" {
710 try testVarInsideInlineLoop(.{ true, @as(u32, 42) });
711}
712
713fn testVarInsideInlineLoop(args: anytype) !void {
714 comptime var i = 0;
715 inline while (i < args.len) : (i += 1) {
716 const x = args[i];
717 if (i == 0) try expect(x);
718 if (i == 1) try expect(x == 42);
719 }
720}
721
722test "*align(1) u16 is the same as *align(1:0:2) u16" {
723 comptime {
724 try expect(*align(1:0:2) u16 == *align(1) u16);
725 try expect(*align(2:0:2) u16 == *u16);
726 }
727}
728
729test "array concatenation of function calls" {
730 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
731 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
733
734 var a = oneItem(3) ++ oneItem(4);
735 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 4 }));
736}
737
738test "array multiplication of function calls" {
739 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
740 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
741 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
742
743 var a = oneItem(3) ** scalar(2);
744 try expect(std.mem.eql(i32, &a, &[_]i32{ 3, 3 }));
745}
746
747fn oneItem(x: i32) [1]i32 {
748 return [_]i32{x};
749}
750
751fn scalar(x: u32) u32 {
752 return x;
753}
754
755test "array concatenation peer resolves element types - value" {
756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
758
759 var a = [2]u3{ 1, 7 };
760 var b = [3]u8{ 200, 225, 255 };
761 _ = .{ &a, &b };
762 const c = a ++ b;
763 comptime assert(@TypeOf(c) == [5]u8);
764 try expect(c[0] == 1);
765 try expect(c[1] == 7);
766 try expect(c[2] == 200);
767 try expect(c[3] == 225);
768 try expect(c[4] == 255);
769}
770
771test "array concatenation peer resolves element types - pointer" {
772 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
773 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
774 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
775
776 var a = [2]u3{ 1, 7 };
777 var b = [3]u8{ 200, 225, 255 };
778 const c = &a ++ &b;
779 comptime assert(@TypeOf(c) == *const [5]u8);
780 try expect(c[0] == 1);
781 try expect(c[1] == 7);
782 try expect(c[2] == 200);
783 try expect(c[3] == 225);
784 try expect(c[4] == 255);
785}
786
787test "array concatenation sets the sentinel - value" {
788 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
789 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
791 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
792
793 var a = [2]u3{ 1, 7 };
794 var b = [3:69]u8{ 200, 225, 255 };
795 _ = .{ &a, &b };
796 const c = a ++ b;
797 comptime assert(@TypeOf(c) == [5:69]u8);
798 try expect(c[0] == 1);
799 try expect(c[1] == 7);
800 try expect(c[2] == 200);
801 try expect(c[3] == 225);
802 try expect(c[4] == 255);
803 const ptr: [*]const u8 = &c;
804 try expect(ptr[5] == 69);
805}
806
807test "array concatenation sets the sentinel - pointer" {
808 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
809 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
810 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
811
812 var a = [2]u3{ 1, 7 };
813 var b = [3:69]u8{ 200, 225, 255 };
814 const c = &a ++ &b;
815 comptime assert(@TypeOf(c) == *const [5:69]u8);
816 try expect(c[0] == 1);
817 try expect(c[1] == 7);
818 try expect(c[2] == 200);
819 try expect(c[3] == 225);
820 try expect(c[4] == 255);
821 const ptr: [*]const u8 = c;
822 try expect(ptr[5] == 69);
823}
824
825test "array multiplication sets the sentinel - value" {
826 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
828 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
830
831 var a = [2:7]u3{ 1, 6 };
832 _ = &a;
833 const b = a ** 2;
834 comptime assert(@TypeOf(b) == [4:7]u3);
835 try expect(b[0] == 1);
836 try expect(b[1] == 6);
837 try expect(b[2] == 1);
838 try expect(b[3] == 6);
839 const ptr: [*]const u3 = &b;
840 try expect(ptr[4] == 7);
841}
842
843test "array multiplication sets the sentinel - pointer" {
844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
846 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
847 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
848
849 var a = [2:7]u3{ 1, 6 };
850 const b = &a ** 2;
851 comptime assert(@TypeOf(b) == *const [4:7]u3);
852 try expect(b[0] == 1);
853 try expect(b[1] == 6);
854 try expect(b[2] == 1);
855 try expect(b[3] == 6);
856 const ptr: [*]const u3 = b;
857 try expect(ptr[4] == 7);
858}
859
860test "comptime assign int to optional int" {
861 comptime {
862 var x: ?i32 = null;
863 x = 2;
864 x.? *= 10;
865 try expectEqual(20, x.?);
866 }
867}
868
869test "two comptime calls with array default initialized to undefined" {
870 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
871 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
872
873 const S = struct {
874 const A = struct {
875 c: B = B{},
876
877 pub fn d() void {
878 var f: A = .{};
879 f.e();
880 }
881
882 pub fn e(g: A) void {
883 _ = g;
884 }
885 };
886
887 const B = struct {
888 buffer: [255]u8 = undefined,
889 };
890 };
891
892 comptime {
893 S.A.d();
894 S.A.d();
895 }
896}
897
898test "const type-annotated local initialized with function call has correct type" {
899 const S = struct {
900 fn foo() comptime_int {
901 return 1234;
902 }
903 };
904 const x: u64 = S.foo();
905 try expect(@TypeOf(x) == u64);
906 try expect(x == 1234);
907}
908
909test "comptime pointer load through elem_ptr" {
910 const S = struct {
911 x: usize,
912 };
913
914 comptime {
915 var array: [10]S = undefined;
916 for (&array, 0..) |*elem, i| {
917 elem.* = .{
918 .x = i,
919 };
920 }
921 var ptr: [*]S = @ptrCast(&array);
922 const x = ptr[0].x;
923 assert(x == 0);
924 ptr += 1;
925 assert(ptr[1].x == 2);
926 }
927}
928
929test "debug variable type resolved through indirect zero-bit types" {
930 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
931
932 const T = struct { key: []void };
933 const slice: []const T = &[_]T{};
934 _ = slice;
935}
936
937test "const local with comptime init through array init" {
938 const E1 = enum {
939 A,
940 pub fn a() void {}
941 };
942
943 const S = struct {
944 fn declarations(comptime T: type) []const std.builtin.Type.Declaration {
945 return @typeInfo(T).@"enum".decls;
946 }
947 };
948
949 const decls = comptime [_][]const std.builtin.Type.Declaration{
950 S.declarations(E1),
951 };
952
953 comptime assert(decls[0][0].name[0] == 'a');
954}
955
956test "closure capture type of runtime-known parameter" {
957 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
958
959 const S = struct {
960 fn b(c: anytype) !void {
961 const D = struct { c: @TypeOf(c) };
962 const d: D = .{ .c = c };
963 try expect(d.c == 1234);
964 }
965 };
966 var c: i32 = 1234;
967 _ = &c;
968 try S.b(c);
969}
970
971test "closure capture type of runtime-known var" {
972 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
973
974 var x: u32 = 1234;
975 _ = &x;
976 const S = struct { val: @TypeOf(x + 100) };
977 const s: S = .{ .val = x };
978 try expect(s.val == 1234);
979}
980
981test "comptime break passing through runtime condition converted to runtime break" {
982 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
983
984 const S = struct {
985 fn doTheTest() !void {
986 var runtime: u8 = 'b';
987 _ = &runtime;
988 inline for ([3]u8{ 'a', 'b', 'c' }) |byte| {
989 bar();
990 if (byte == runtime) {
991 foo(byte);
992 break;
993 }
994 }
995 try expect(ok);
996 try expect(count == 2);
997 }
998 var ok = false;
999 var count: usize = 0;
1000
1001 fn foo(byte: u8) void {
1002 ok = byte == 'b';
1003 }
1004
1005 fn bar() void {
1006 count += 1;
1007 }
1008 };
1009
1010 try S.doTheTest();
1011}
1012
1013test "comptime break to outer loop passing through runtime condition converted to runtime break" {
1014 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1015 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1016
1017 const S = struct {
1018 fn doTheTest() !void {
1019 var runtime: u8 = 'b';
1020 _ = &runtime;
1021 outer: inline for ([3]u8{ 'A', 'B', 'C' }) |outer_byte| {
1022 inline for ([3]u8{ 'a', 'b', 'c' }) |byte| {
1023 bar(outer_byte);
1024 if (byte == runtime) {
1025 foo(byte);
1026 break :outer;
1027 }
1028 }
1029 }
1030 try expect(ok);
1031 try expect(count == 2);
1032 }
1033 var ok = false;
1034 var count: usize = 0;
1035
1036 fn foo(byte: u8) void {
1037 ok = byte == 'b';
1038 }
1039
1040 fn bar(byte: u8) void {
1041 _ = byte;
1042 count += 1;
1043 }
1044 };
1045
1046 try S.doTheTest();
1047}
1048
1049test "comptime break operand passing through runtime condition converted to runtime break" {
1050 const S = struct {
1051 fn doTheTest(runtime: u8) !void {
1052 const result = inline for ([3]u8{ 'a', 'b', 'c' }) |byte| {
1053 if (byte == runtime) {
1054 break runtime;
1055 }
1056 } else 'z';
1057 try expect(result == 'b');
1058 }
1059 };
1060
1061 try S.doTheTest('b');
1062 try comptime S.doTheTest('b');
1063}
1064
1065test "comptime break operand passing through runtime switch converted to runtime break" {
1066 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1067
1068 const S = struct {
1069 fn doTheTest(runtime: u8) !void {
1070 const result = inline for ([3]u8{ 'a', 'b', 'c' }) |byte| {
1071 switch (runtime) {
1072 byte => break runtime,
1073 else => {},
1074 }
1075 } else 'z';
1076 try expect(result == 'b');
1077 }
1078 };
1079
1080 try S.doTheTest('b');
1081 try comptime S.doTheTest('b');
1082}
1083
1084test "no dependency loop for alignment of self struct" {
1085 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1086 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1087 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1088
1089 const S = struct {
1090 fn doTheTest() !void {
1091 var a: namespace.A = undefined;
1092 a.d = .{ .g = &buf };
1093 a.d.g[3] = 42;
1094 a.d.g[3] += 1;
1095 try expect(a.d.g[3] == 43);
1096 }
1097
1098 var buf: [10]u8 align(@alignOf([*]u8)) = undefined;
1099
1100 const namespace = struct {
1101 const B = struct { a: A };
1102 const A = C(B);
1103 };
1104
1105 pub fn C(comptime B: type) type {
1106 return struct {
1107 d: D(F) = .{},
1108
1109 const F = struct { b: B };
1110 };
1111 }
1112
1113 pub fn D(comptime F: type) type {
1114 return struct {
1115 g: [*]align(@alignOf(F)) u8 = undefined,
1116 };
1117 }
1118 };
1119 try S.doTheTest();
1120}
1121
1122test "no dependency loop for alignment of self bare union" {
1123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1124 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1125 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1126
1127 const S = struct {
1128 fn doTheTest() !void {
1129 var a: namespace.A = undefined;
1130 a.d = .{ .g = &buf };
1131 a.d.g[3] = 42;
1132 a.d.g[3] += 1;
1133 try expect(a.d.g[3] == 43);
1134 }
1135
1136 var buf: [10]u8 align(@alignOf([*]u8)) = undefined;
1137
1138 const namespace = struct {
1139 const B = union { a: A, b: void };
1140 const A = C(B);
1141 };
1142
1143 pub fn C(comptime B: type) type {
1144 return struct {
1145 d: D(F) = .{},
1146
1147 const F = struct { b: B };
1148 };
1149 }
1150
1151 pub fn D(comptime F: type) type {
1152 return struct {
1153 g: [*]align(@alignOf(F)) u8 = undefined,
1154 };
1155 }
1156 };
1157 try S.doTheTest();
1158}
1159
1160test "no dependency loop for alignment of self tagged union" {
1161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1164
1165 const S = struct {
1166 fn doTheTest() !void {
1167 var a: namespace.A = undefined;
1168 a.d = .{ .g = &buf };
1169 a.d.g[3] = 42;
1170 a.d.g[3] += 1;
1171 try expect(a.d.g[3] == 43);
1172 }
1173
1174 var buf: [10]u8 align(@alignOf([*]u8)) = undefined;
1175
1176 const namespace = struct {
1177 const B = union(enum) { a: A, b: void };
1178 const A = C(B);
1179 };
1180
1181 pub fn C(comptime B: type) type {
1182 return struct {
1183 d: D(F) = .{},
1184
1185 const F = struct { b: B };
1186 };
1187 }
1188
1189 pub fn D(comptime F: type) type {
1190 return struct {
1191 g: [*]align(@alignOf(F)) u8 = undefined,
1192 };
1193 }
1194 };
1195 try S.doTheTest();
1196}
1197
1198test "equality of pointers to comptime const" {
1199 const a: i32 = undefined;
1200 comptime assert(&a == &a);
1201}
1202
1203test "storing an array of type in a field" {
1204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1207
1208 const S = struct {
1209 fn doTheTest() void {
1210 const foobar = Foobar.foo();
1211 foo(foobar.str[0..10]);
1212 }
1213 const Foobar = struct {
1214 myTypes: [128]type,
1215 str: [1024]u8,
1216
1217 fn foo() @This() {
1218 comptime var foobar: Foobar = undefined;
1219 foobar.str = [_]u8{'a'} ** 1024;
1220 return foobar;
1221 }
1222 };
1223
1224 fn foo(arg: anytype) void {
1225 _ = arg;
1226 }
1227 };
1228
1229 S.doTheTest();
1230}
1231
1232test "pass pointer to field of comptime-only type as a runtime parameter" {
1233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1234 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1235
1236 const S = struct {
1237 const Mixed = struct {
1238 T: type,
1239 x: i32,
1240 };
1241 const bag: Mixed = .{
1242 .T = bool,
1243 .x = 1234,
1244 };
1245
1246 var ok = false;
1247
1248 fn doTheTest() !void {
1249 foo(&bag.x);
1250 try expect(ok);
1251 }
1252
1253 fn foo(ptr: *const i32) void {
1254 ok = ptr.* == 1234;
1255 }
1256 };
1257 try S.doTheTest();
1258}
1259
1260test "comptime write through extern struct reinterpreted as array" {
1261 comptime {
1262 const S = extern struct {
1263 a: u8,
1264 b: u8,
1265 c: u8,
1266 };
1267 var s: S = undefined;
1268 @as(*[3]u8, @ptrCast(&s))[0] = 1;
1269 @as(*[3]u8, @ptrCast(&s))[1] = 2;
1270 @as(*[3]u8, @ptrCast(&s))[2] = 3;
1271 assert(s.a == 1);
1272 assert(s.b == 2);
1273 assert(s.c == 3);
1274 }
1275}
1276
1277test "continue nested in a conditional in an inline for" {
1278 var x: u32 = 1;
1279 inline for ([_]u8{ 1, 2, 3 }) |_| {
1280 if (1 == 1) {
1281 x = 0;
1282 continue;
1283 }
1284 }
1285 try expect(x == 0);
1286}
1287
1288test "optional pointer represented as a pointer value" {
1289 comptime {
1290 var val: u8 = 15;
1291 const opt_ptr: ?*u8 = &val;
1292
1293 const payload_ptr = &opt_ptr.?;
1294 try expect(payload_ptr.*.* == 15);
1295 }
1296}
1297
1298test "mutate through pointer-like optional at comptime" {
1299 comptime {
1300 var val: u8 = 15;
1301 var opt_ptr: ?*const u8 = &val;
1302
1303 const payload_ptr = &opt_ptr.?;
1304 payload_ptr.* = &@as(u8, 16);
1305 try expect(payload_ptr.*.* == 16);
1306 }
1307}
1308
1309test "repeated value is correctly expanded" {
1310 const S = struct { x: [4]i8 = std.mem.zeroes([4]i8) };
1311 const M = struct { x: [4]S = std.mem.zeroes([4]S) };
1312
1313 comptime {
1314 var res = M{};
1315 for (.{ 1, 2, 3 }) |i| res.x[i].x[i] = i;
1316
1317 try expectEqual(M{ .x = .{
1318 .{ .x = .{ 0, 0, 0, 0 } },
1319 .{ .x = .{ 0, 1, 0, 0 } },
1320 .{ .x = .{ 0, 0, 2, 0 } },
1321 .{ .x = .{ 0, 0, 0, 3 } },
1322 } }, res);
1323 }
1324}
1325
1326test "value in if block is comptime-known" {
1327 const first = blk: {
1328 const s = if (false) "a" else "b";
1329 break :blk "foo" ++ s;
1330 };
1331 const second = blk: {
1332 const S = struct { str: []const u8 };
1333 const s = if (false) S{ .str = "a" } else S{ .str = "b" };
1334 break :blk "foo" ++ s.str;
1335 };
1336 comptime assert(std.mem.eql(u8, first, second));
1337}
1338
1339test "lazy sizeof is resolved in division" {
1340 const A = struct {
1341 a: u32,
1342 };
1343 const a = 2;
1344 try expect(@sizeOf(A) / a == 2);
1345 try expect(@sizeOf(A) - a == 2);
1346}
1347
1348test "lazy sizeof union tag size in compare" {
1349 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1350
1351 const A = union(enum) {
1352 a: void,
1353 b: void,
1354 };
1355 try expect(@sizeOf(A) == 1);
1356}
1357
1358test "lazy value is resolved as slice operand" {
1359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1361 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1362 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1363
1364 const A = struct { a: u32 };
1365 var a: [512]u64 = undefined;
1366
1367 const ptr1 = a[0..@sizeOf(A)];
1368 const ptr2 = @as([*]u8, @ptrCast(&a))[0..@sizeOf(A)];
1369 try expect(@intFromPtr(ptr1) == @intFromPtr(ptr2));
1370 try expect(ptr1.len == ptr2.len);
1371}
1372
1373test "break from inline loop depends on runtime condition" {
1374 const S = struct {
1375 fn foo(a: u8) bool {
1376 return a == 4;
1377 }
1378 };
1379 const arr = [_]u8{ 1, 2, 3, 4 };
1380 {
1381 const blk = blk: {
1382 inline for (arr) |val| {
1383 if (S.foo(val)) {
1384 break :blk val;
1385 }
1386 }
1387 return error.TestFailed;
1388 };
1389 try expect(blk == 4);
1390 }
1391
1392 {
1393 comptime var i = 0;
1394 const blk = blk: {
1395 inline while (i < arr.len) : (i += 1) {
1396 const val = arr[i];
1397 if (S.foo(val)) {
1398 break :blk val;
1399 }
1400 }
1401 return error.TestFailed;
1402 };
1403 try expect(blk == 4);
1404 }
1405}
1406
1407test "inline for inside a runtime condition" {
1408 var a = false;
1409 _ = &a;
1410 if (a) {
1411 const arr = .{ 1, 2, 3 };
1412 inline for (arr) |val| {
1413 if (val < 3) continue;
1414 try expect(val == 3);
1415 }
1416 }
1417}
1418
1419test "continue in inline for inside a comptime switch" {
1420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1421
1422 const arr = .{ 1, 2, 3 };
1423 var count: u8 = 0;
1424 switch (arr[1]) {
1425 2 => {
1426 inline for (arr) |val| {
1427 if (val == 2) continue;
1428
1429 count += val;
1430 }
1431 },
1432 else => {},
1433 }
1434 try expect(count == 4);
1435}
1436
1437test "length of global array is determinable at comptime" {
1438 const S = struct {
1439 var bytes: [1024]u8 = undefined;
1440
1441 fn foo() !void {
1442 try std.testing.expect(bytes.len == 1024);
1443 }
1444 };
1445 try comptime S.foo();
1446}
1447
1448test "continue nested inline for loop" {
1449 // TODO: https://github.com/ziglang/zig/issues/13175
1450 if (true) return error.SkipZigTest;
1451
1452 var a: u8 = 0;
1453 loop: inline for ([_]u8{ 1, 2 }) |x| {
1454 inline for ([_]u8{1}) |y| {
1455 if (x == y) {
1456 continue :loop;
1457 }
1458 }
1459 a = x;
1460 try expect(x == 2);
1461 }
1462 try expect(a == 2);
1463}
1464
1465test "continue nested inline for loop in named block expr" {
1466 // TODO: https://github.com/ziglang/zig/issues/13175
1467 if (true) return error.SkipZigTest;
1468
1469 var a: u8 = 0;
1470 loop: inline for ([_]u8{ 1, 2 }) |x| {
1471 a = b: {
1472 inline for ([_]u8{1}) |y| {
1473 if (x == y) {
1474 continue :loop;
1475 }
1476 }
1477 break :b x;
1478 };
1479 try expect(x == 2);
1480 }
1481 try expect(a == 2);
1482}
1483
1484test "x and false is comptime-known false" {
1485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1486
1487 const T = struct {
1488 var x: u32 = 0;
1489
1490 fn foo() bool {
1491 x += 1; // Observable side-effect
1492 return true;
1493 }
1494 };
1495
1496 if (T.foo() and T.foo() and false and T.foo()) {
1497 @compileError("Condition should be comptime-known false");
1498 }
1499 try expect(T.x == 2);
1500
1501 T.x = 0;
1502 if (T.foo() and T.foo() and b: {
1503 _ = T.foo();
1504 break :b false;
1505 } and T.foo()) {
1506 @compileError("Condition should be comptime-known false");
1507 }
1508 try expect(T.x == 3);
1509}
1510
1511test "x or true is comptime-known true" {
1512 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1513
1514 const T = struct {
1515 var x: u32 = 0;
1516
1517 fn foo() bool {
1518 x += 1; // Observable side-effect
1519 return false;
1520 }
1521 };
1522
1523 if (!(T.foo() or T.foo() or true or T.foo())) {
1524 @compileError("Condition should be comptime-known false");
1525 }
1526 try expect(T.x == 2);
1527
1528 T.x = 0;
1529 if (!(T.foo() or T.foo() or b: {
1530 _ = T.foo();
1531 break :b true;
1532 } or T.foo())) {
1533 @compileError("Condition should be comptime-known false");
1534 }
1535 try expect(T.x == 3);
1536}
1537
1538test "non-optional and optional array elements concatenated" {
1539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1542
1543 const array = [1]u8{'A'} ++ [1]?u8{null};
1544 var index: usize = 0;
1545 _ = &index;
1546 try expect(array[index].? == 'A');
1547}
1548
1549test "inline call in @TypeOf inherits is_inline property" {
1550 const S = struct {
1551 inline fn doNothing() void {}
1552 const T = @TypeOf(doNothing());
1553 };
1554 try expect(S.T == void);
1555}
1556
1557test "comptime function turns function value to function pointer" {
1558 const S = struct {
1559 fn fnPtr(function: anytype) *const @TypeOf(function) {
1560 return &function;
1561 }
1562 fn Nil() u8 {
1563 return 0;
1564 }
1565 const foo = &[_]*const fn () u8{
1566 fnPtr(Nil),
1567 };
1568 };
1569 comptime assert(S.foo[0] == &S.Nil);
1570}
1571
1572test "container level const and var have unique addresses" {
1573 const S = struct {
1574 x: i32,
1575 y: i32,
1576 const c = @This(){ .x = 1, .y = 1 };
1577 var v: @This() = c;
1578 };
1579 var p = &S.c;
1580 _ = &p;
1581 try std.testing.expect(p.x == S.c.x);
1582 S.v.x = 2;
1583 try std.testing.expect(p.x == S.c.x);
1584}
1585
1586test "break from block results in type" {
1587 const S = struct {
1588 fn NewType(comptime T: type) type {
1589 const Padded = blk: {
1590 if (@sizeOf(T) <= @sizeOf(usize)) break :blk void;
1591 break :blk T;
1592 };
1593
1594 return Padded;
1595 }
1596 };
1597 const T = S.NewType(usize);
1598 try expect(T == void);
1599}
1600
1601test "struct in comptime false branch is not evaluated" {
1602 const S = struct {
1603 const comptime_const = 2;
1604 fn some(comptime V: type) type {
1605 return switch (comptime_const) {
1606 3 => struct { a: V.foo },
1607 2 => V,
1608 else => unreachable,
1609 };
1610 }
1611 };
1612 try expect(S.some(u32) == u32);
1613}
1614
1615test "result of nested switch assigned to variable" {
1616 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
1617
1618 var zds: u32 = 0;
1619 zds = switch (zds) {
1620 0 => switch (zds) {
1621 0...0 => 1234,
1622 1...1 => zds,
1623 2 => zds,
1624 else => return,
1625 },
1626 else => zds,
1627 };
1628 try expect(zds == 1234);
1629}
1630
1631test "inline for loop of functions returning error unions" {
1632 const T1 = struct {
1633 fn v() error{}!usize {
1634 return 1;
1635 }
1636 };
1637 const T2 = struct {
1638 fn v() error{Error}!usize {
1639 return 2;
1640 }
1641 };
1642 var a: usize = 0;
1643 inline for (.{ T1, T2 }) |T| {
1644 a += try T.v();
1645 }
1646 try expect(a == 3);
1647}
1648
1649test "if inside a switch" {
1650 var condition = true;
1651 var wave_type: u32 = 0;
1652 _ = .{ &condition, &wave_type };
1653 const sample: i32 = switch (wave_type) {
1654 0 => if (condition) 2 else 3,
1655 1 => 100,
1656 2 => 200,
1657 3 => 300,
1658 else => unreachable,
1659 };
1660 try expect(sample == 2);
1661}
1662
1663test "function has correct return type when previous return is casted to smaller type" {
1664 const S = struct {
1665 fn foo(b: bool) u16 {
1666 if (b) return @as(u8, 0xFF);
1667 return 0xFFFF;
1668 }
1669 };
1670 try expect(S.foo(true) == 0xFF);
1671}
1672
1673test "early exit in container level const" {
1674 const S = struct {
1675 const value = blk: {
1676 if (true) {
1677 break :blk @as(u32, 1);
1678 }
1679 break :blk @as(u32, 0);
1680 };
1681 };
1682 try expect(S.value == 1);
1683}
1684
1685test "@inComptime" {
1686 const S = struct {
1687 fn inComptime() bool {
1688 return @inComptime();
1689 }
1690 };
1691 try expectEqual(false, @inComptime());
1692 try expectEqual(false, S.inComptime());
1693 try expectEqual(true, comptime S.inComptime());
1694}
1695
1696// comptime partial array assign
1697comptime {
1698 var foo = [3]u8{ 0x55, 0x55, 0x55 };
1699 var bar = [2]u8{ 1, 2 };
1700 _ = .{ &foo, &bar };
1701 foo[0..2].* = bar;
1702 assert(foo[0] == 1);
1703 assert(foo[1] == 2);
1704 assert(foo[2] == 0x55);
1705}
1706
1707test "const with allocation before result is comptime-known" {
1708 const x = blk: {
1709 const y = [1]u32{2};
1710 _ = y;
1711 break :blk [1]u32{42};
1712 };
1713 comptime assert(@TypeOf(x) == [1]u32);
1714 comptime assert(x[0] == 42);
1715}
1716
1717test "const with specified type initialized with typed array is comptime-known" {
1718 const x: [3]u16 = [3]u16{ 1, 2, 3 };
1719 comptime assert(@TypeOf(x) == [3]u16);
1720 comptime assert(x[0] == 1);
1721 comptime assert(x[1] == 2);
1722 comptime assert(x[2] == 3);
1723}
1724
1725test "block with comptime-known result but possible runtime exit is comptime-known" {
1726 var t: bool = true;
1727 _ = &t;
1728
1729 const a: comptime_int = a: {
1730 if (!t) return error.TestFailed;
1731 break :a 123;
1732 };
1733
1734 const b: comptime_int = b: {
1735 if (t) break :b 456;
1736 return error.TestFailed;
1737 };
1738
1739 comptime assert(a == 123);
1740 comptime assert(b == 456);
1741}
1742
1743test "comptime labeled block implicit exit" {
1744 const result = comptime b: {
1745 if (false) break :b 123;
1746 };
1747 comptime assert(result == {});
1748}
1749
1750test "comptime block has intermediate runtime-known values" {
1751 const arr: [2]u8 = .{ 1, 2 };
1752
1753 var idx: usize = undefined;
1754 idx = 0;
1755
1756 comptime {
1757 _ = arr[idx];
1758 }
1759}