master
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const mem = std.mem;
5const expect = std.testing.expect;
6const expectEqualStrings = std.testing.expectEqualStrings;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18test "truncate" {
19 try expect(testTruncate(0x10fd) == 0xfd);
20 comptime assert(testTruncate(0x10fd) == 0xfd);
21}
22fn testTruncate(x: u32) u8 {
23 return @as(u8, @truncate(x));
24}
25
26test "truncate to non-power-of-two integers" {
27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
29
30 try testTrunc(u32, u1, 0b10101, 0b1);
31 try testTrunc(u32, u1, 0b10110, 0b0);
32 try testTrunc(u32, u2, 0b10101, 0b01);
33 try testTrunc(u32, u2, 0b10110, 0b10);
34 try testTrunc(i32, i5, -4, -4);
35 try testTrunc(i32, i5, 4, 4);
36 try testTrunc(i32, i5, -28, 4);
37 try testTrunc(i32, i5, 28, -4);
38 try testTrunc(i32, i5, std.math.maxInt(i32), -1);
39}
40
41test "truncate to non-power-of-two integers from 128-bit" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
45
46 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010101, 0x01);
47 try testTrunc(u128, u1, 0xffffffff_ffffffff_ffffffff_01010110, 0x00);
48 try testTrunc(u128, u2, 0xffffffff_ffffffff_ffffffff_01010101, 0x01);
49 try testTrunc(u128, u2, 0xffffffff_ffffffff_ffffffff_01010102, 0x02);
50 try testTrunc(i128, i5, -4, -4);
51 try testTrunc(i128, i5, 4, 4);
52 try testTrunc(i128, i5, -28, 4);
53 try testTrunc(i128, i5, 28, -4);
54 try testTrunc(i128, i5, std.math.maxInt(i128), -1);
55}
56
57fn testTrunc(comptime Big: type, comptime Little: type, big: Big, little: Little) !void {
58 try expect(@as(Little, @truncate(big)) == little);
59}
60
61const g1: i32 = 1233 + 1;
62var g2: i32 = 0;
63
64test "global variables" {
65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
66
67 try expect(g2 == 0);
68 g2 = g1;
69 try expect(g2 == 1234);
70}
71
72test "comptime keyword on expressions" {
73 const x: i32 = comptime x: {
74 break :x 1 + 2 + 3;
75 };
76 try expect(x == comptime 6);
77}
78
79test "type equality" {
80 try expect(*const u8 != *u8);
81}
82
83test "pointer dereferencing" {
84 var x = @as(i32, 3);
85 const y = &x;
86
87 y.* += 1;
88
89 try expect(x == 4);
90 try expect(y.* == 4);
91}
92
93test "const expression eval handling of variables" {
94 var x = true;
95 while (x) {
96 x = false;
97 }
98}
99
100test "character literals" {
101 try expect('\'' == single_quote);
102}
103const single_quote = '\'';
104
105test "non const ptr to aliased type" {
106 const int = i32;
107 try expect(?*int == ?*i32);
108}
109
110test "function branch hints" {
111 const S = struct {
112 fn none() void {
113 @branchHint(.none);
114 }
115 fn likely() void {
116 @branchHint(.likely);
117 }
118 fn unlikely() void {
119 @branchHint(.unlikely);
120 }
121 fn cold() void {
122 @branchHint(.cold);
123 }
124 fn unpredictable() void {
125 @branchHint(.unpredictable);
126 }
127 };
128 S.none();
129 S.likely();
130 S.unlikely();
131 S.cold();
132 S.unpredictable();
133 comptime S.none();
134 comptime S.likely();
135 comptime S.unlikely();
136 comptime S.cold();
137 comptime S.unpredictable();
138}
139
140test "if branch hints" {
141 var t: bool = undefined;
142 t = true;
143 if (t) {
144 @branchHint(.likely);
145 } else {
146 @branchHint(.cold);
147 }
148}
149
150test "switch branch hints" {
151 var t: bool = undefined;
152 t = true;
153 switch (t) {
154 true => {
155 @branchHint(.likely);
156 },
157 false => {
158 @branchHint(.cold);
159 },
160 }
161}
162
163test "orelse branch hints" {
164 var x: ?u32 = undefined;
165 x = 123;
166 const val = x orelse val: {
167 @branchHint(.cold);
168 break :val 456;
169 };
170 try expect(val == 123);
171}
172
173test "catch branch hints" {
174 var x: error{Bad}!u32 = undefined;
175 x = 123;
176 const val = x catch val: {
177 @branchHint(.cold);
178 break :val 456;
179 };
180 try expect(val == 123);
181}
182
183test "and/or branch hints" {
184 var t: bool = undefined;
185 t = true;
186 try expect(t or b: {
187 @branchHint(.unlikely);
188 break :b false;
189 });
190 try expect(t and b: {
191 @branchHint(.likely);
192 break :b true;
193 });
194}
195
196test "unicode escape in character literal" {
197 var a: u24 = '\u{01f4a9}';
198 _ = &a;
199 try expect(a == 128169);
200}
201
202test "unicode character in character literal" {
203 try expect('💩' == 128169);
204}
205
206fn first4KeysOfHomeRow() []const u8 {
207 return "aoeu";
208}
209
210test "return string from function" {
211 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
213
214 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
215}
216
217test "hex escape" {
218 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
220
221 try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
222}
223
224test "multiline string" {
225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
227
228 const s1 =
229 \\one
230 \\two)
231 \\three
232 ;
233 const s2 = "one\ntwo)\nthree";
234 try expect(mem.eql(u8, s1, s2));
235}
236
237test "multiline string comments at start" {
238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
240
241 const s1 =
242 //\\one
243 \\two)
244 \\three
245 ;
246 const s2 = "two)\nthree";
247 try expect(mem.eql(u8, s1, s2));
248}
249
250test "multiline string comments at end" {
251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
252 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
253
254 const s1 =
255 \\one
256 \\two)
257 //\\three
258 ;
259 const s2 = "one\ntwo)";
260 try expect(mem.eql(u8, s1, s2));
261}
262
263test "multiline string comments in middle" {
264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
266
267 const s1 =
268 \\one
269 //\\two)
270 \\three
271 ;
272 const s2 = "one\nthree";
273 try expect(mem.eql(u8, s1, s2));
274}
275
276test "multiline string comments at multiple places" {
277 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
279
280 const s1 =
281 \\one
282 //\\two
283 \\three
284 //\\four
285 \\five
286 ;
287 const s2 = "one\nthree\nfive";
288 try expect(mem.eql(u8, s1, s2));
289}
290
291test "string concatenation simple" {
292 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
293
294 try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
295}
296
297test "array mult operator" {
298 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
299 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
300
301 try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
302}
303
304const global_a: i32 = 1234;
305const global_b: *const i32 = &global_a;
306const global_c: *const f32 = @as(*const f32, @ptrCast(global_b));
307test "compile time global reinterpret" {
308 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
309
310 const d = @as(*const i32, @ptrCast(global_c));
311 try expect(d.* == 1234);
312}
313
314test "cast undefined" {
315 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
316
317 const array: [100]u8 = undefined;
318 const slice = @as([]const u8, &array);
319 testCastUndefined(slice);
320}
321fn testCastUndefined(x: []const u8) void {
322 _ = x;
323}
324
325test "implicit cast after unreachable" {
326 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
327 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
328
329 try expect(outer() == 1234);
330}
331fn inner() i32 {
332 return 1234;
333}
334fn outer() i64 {
335 return inner();
336}
337
338test "comptime if inside runtime while which unconditionally breaks" {
339 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
340 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
341}
342fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
343 while (cond) {
344 if (false) {}
345 break;
346 }
347}
348
349test "implicit comptime while" {
350 while (false) {
351 @compileError("bad");
352 }
353}
354
355fn fnThatClosesOverLocalConst() type {
356 const c = 1;
357 return struct {
358 fn g() i32 {
359 return c;
360 }
361 };
362}
363
364test "function closes over local const" {
365 const x = fnThatClosesOverLocalConst().g();
366 try expect(x == 1);
367}
368
369test "volatile load and store" {
370 var number: i32 = 1234;
371 const ptr = @as(*volatile i32, &number);
372 ptr.* += 1;
373 try expect(ptr.* == 1235);
374}
375
376fn fA() []const u8 {
377 return "a";
378}
379fn fB() []const u8 {
380 return "b";
381}
382
383test "call function pointer in struct" {
384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
386
387 try expect(mem.eql(u8, f3(true), "a"));
388 try expect(mem.eql(u8, f3(false), "b"));
389}
390
391fn f3(x: bool) []const u8 {
392 var wrapper: FnPtrWrapper = .{
393 .fn_ptr = fB,
394 };
395
396 if (x) {
397 wrapper.fn_ptr = fA;
398 }
399
400 return wrapper.fn_ptr();
401}
402
403const FnPtrWrapper = struct {
404 fn_ptr: *const fn () []const u8,
405};
406
407test "const ptr from var variable" {
408 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
409
410 var x: u64 = undefined;
411 var y: u64 = undefined;
412
413 x = 78;
414 copy(&x, &y);
415
416 try expect(x == y);
417}
418
419fn copy(src: *const u64, dst: *u64) void {
420 dst.* = src.*;
421}
422
423test "call result of if else expression" {
424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
426 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
427
428 try expect(mem.eql(u8, f2(true), "a"));
429 try expect(mem.eql(u8, f2(false), "b"));
430}
431fn f2(x: bool) []const u8 {
432 return (if (x) &fA else &fB)();
433}
434
435const OpaqueA = opaque {};
436test "variable is allowed to be a pointer to an opaque type" {
437 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
438
439 var x: i32 = 1234;
440 _ = hereIsAnOpaqueType(@as(*OpaqueA, @ptrCast(&x)));
441}
442fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
443 var a = ptr;
444 _ = &a;
445 return a;
446}
447
448test "take address of parameter" {
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
451
452 try testTakeAddressOfParameter(12.34);
453}
454fn testTakeAddressOfParameter(f: f32) !void {
455 const f_ptr = &f;
456 try expect(f_ptr.* == 12.34);
457}
458
459test "pointer to void return type" {
460 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
461
462 try testPointerToVoidReturnType();
463}
464fn testPointerToVoidReturnType() anyerror!void {
465 const a = testPointerToVoidReturnType2();
466 return a.*;
467}
468const test_pointer_to_void_return_type_x = void{};
469fn testPointerToVoidReturnType2() *const void {
470 return &test_pointer_to_void_return_type_x;
471}
472
473test "array 2D const double ptr" {
474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
477
478 const rect_2d_vertexes = [_][1]f32{
479 [_]f32{1.0},
480 [_]f32{2.0},
481 };
482 try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
483}
484
485test "array 2D const double ptr with offset" {
486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
488 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
489
490 const rect_2d_vertexes = [_][2]f32{
491 [_]f32{ 3.0, 4.239 },
492 [_]f32{ 1.0, 2.0 },
493 };
494 try testArray2DConstDoublePtr(&rect_2d_vertexes[1][0]);
495}
496
497test "array 3D const double ptr with offset" {
498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
500 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
501
502 const rect_3d_vertexes = [_][2][2]f32{
503 [_][2]f32{
504 [_]f32{ 3.0, 4.239 },
505 [_]f32{ 3.5, 7.2 },
506 },
507 [_][2]f32{
508 [_]f32{ 3.0, 4.239 },
509 [_]f32{ 1.0, 2.0 },
510 },
511 };
512 try testArray2DConstDoublePtr(&rect_3d_vertexes[1][1][0]);
513}
514
515fn testArray2DConstDoublePtr(ptr: *const f32) !void {
516 const ptr2 = @as([*]const f32, @ptrCast(ptr));
517 try expect(ptr2[0] == 1.0);
518 try expect(ptr2[1] == 2.0);
519}
520
521test "double implicit cast in same expression" {
522 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
523
524 var x = @as(i32, @as(u16, nine()));
525 _ = &x;
526 try expect(x == 9);
527}
528fn nine() u8 {
529 return 9;
530}
531
532test "struct inside function" {
533 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
534
535 try testStructInFn();
536 try comptime testStructInFn();
537}
538
539fn testStructInFn() !void {
540 const BlockKind = u32;
541
542 const Block = struct {
543 kind: BlockKind,
544 };
545
546 var block = Block{ .kind = 1234 };
547
548 block.kind += 1;
549
550 try expect(block.kind == 1235);
551}
552
553test "fn call returning scalar optional in equality expression" {
554 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
555 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
556
557 try expect(getNull() == null);
558}
559
560fn getNull() ?*i32 {
561 return null;
562}
563
564test "global variable assignment with optional unwrapping with var initialized to undefined" {
565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
567 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
568
569 const S = struct {
570 var data: i32 = 1234;
571 fn foo() ?*i32 {
572 return &data;
573 }
574 };
575 global_foo = S.foo() orelse {
576 @panic("bad");
577 };
578 try expect(global_foo.* == 1234);
579}
580
581var global_foo: *i32 = undefined;
582
583test "peer result location with typed parent, runtime condition, comptime prongs" {
584 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
585
586 const S = struct {
587 fn doTheTest(arg: i32) i32 {
588 const st = Structy{
589 .bleh = if (arg == 1) 1 else 1,
590 };
591
592 if (st.bleh == 1)
593 return 1234;
594 return 0;
595 }
596
597 const Structy = struct {
598 bleh: i32,
599 };
600 };
601 try expect(S.doTheTest(0) == 1234);
602 try expect(S.doTheTest(1) == 1234);
603}
604
605test "non-ambiguous reference of shadowed decls" {
606 try expect(ZA().B().Self != ZA().Self);
607}
608
609fn ZA() type {
610 return struct {
611 b: B(),
612
613 const Self = @This();
614
615 fn B() type {
616 return struct {
617 const Self = @This();
618 };
619 }
620 };
621}
622
623test "use of declaration with same name as primitive" {
624 const S = struct {
625 const @"u8" = u16;
626 const alias = @"u8";
627 };
628 const a: S.u8 = 300;
629 try expect(a == 300);
630
631 const b: S.alias = 300;
632 try expect(b == 300);
633
634 const @"u8" = u16;
635 const c: @"u8" = 300;
636 try expect(c == 300);
637}
638
639test "constant equal function pointers" {
640 const alias = emptyFn;
641 try expect(comptime x: {
642 break :x emptyFn == alias;
643 });
644}
645
646fn emptyFn() void {}
647
648const addr1 = @as(*const u8, @ptrCast(&emptyFn));
649test "comptime cast fn to ptr" {
650 const addr2 = @as(*const u8, @ptrCast(&emptyFn));
651 comptime assert(addr1 == addr2);
652}
653
654test "equality compare fn ptrs" {
655 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Uses function pointers
656
657 var a = &emptyFn;
658 _ = &a;
659 try expect(a == a);
660}
661
662test "self reference through fn ptr field" {
663 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
664
665 const S = struct {
666 const A = struct {
667 f: *const fn (A) u8,
668 };
669
670 fn foo(a: A) u8 {
671 _ = a;
672 return 12;
673 }
674 };
675 var a: S.A = undefined;
676 a.f = S.foo;
677 try expect(a.f(a) == 12);
678}
679
680test "global variable initialized to global variable array element" {
681 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
682 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
683
684 try expect(global_ptr == &gdt[0]);
685}
686const GDTEntry = struct {
687 field: i32,
688};
689var gdt = [_]GDTEntry{
690 GDTEntry{ .field = 1 },
691 GDTEntry{ .field = 2 },
692};
693var global_ptr = &gdt[0];
694
695test "global constant is loaded with a runtime-known index" {
696 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
697
698 const S = struct {
699 fn doTheTest() !void {
700 var index: usize = 1;
701 _ = &index;
702 const ptr = &pieces[index].field;
703 try expect(ptr.* == 2);
704 }
705 const Piece = struct {
706 field: i32,
707 };
708 const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } };
709 };
710 try S.doTheTest();
711}
712
713test "multiline string literal is null terminated" {
714 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
715
716 const s1 =
717 \\one
718 \\two)
719 \\three
720 ;
721 const s2 = "one\ntwo)\nthree";
722 try expect(std.mem.orderZ(u8, s1, s2) == .eq);
723}
724
725test "string escapes" {
726 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
727 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
729
730 try expectEqualStrings("\"", "\x22");
731 try expectEqualStrings("\'", "\x27");
732 try expectEqualStrings("\n", "\x0a");
733 try expectEqualStrings("\r", "\x0d");
734 try expectEqualStrings("\t", "\x09");
735 try expectEqualStrings("\\", "\x5c");
736 try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
737}
738
739test "explicit cast optional pointers" {
740 const a: ?*i32 = undefined;
741 const b: ?*f32 = @as(?*f32, @ptrCast(a));
742 _ = b;
743}
744
745test "pointer comparison" {
746 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
747
748 const a = @as([]const u8, "a");
749 const b = &a;
750 try expect(ptrEql(b, b));
751}
752fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
753 return a == b;
754}
755
756test "string concatenation" {
757 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
758 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
759
760 const a = "OK" ++ " IT " ++ "WORKED";
761 const b = "OK IT WORKED";
762
763 comptime assert(@TypeOf(a) == *const [12:0]u8);
764 comptime assert(@TypeOf(b) == *const [12:0]u8);
765
766 const len = b.len;
767 const len_with_null = len + 1;
768 {
769 var i: u32 = 0;
770 while (i < len_with_null) : (i += 1) {
771 try expect(a[i] == b[i]);
772 }
773 }
774 try expect(a[len] == 0);
775 try expect(b[len] == 0);
776}
777
778test "result location is optional inside error union" {
779 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
780 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
781
782 const x = maybe(true) catch unreachable;
783 try expect(x.? == 42);
784}
785
786fn maybe(x: bool) anyerror!?u32 {
787 return switch (x) {
788 true => @as(u32, 42),
789 else => null,
790 };
791}
792
793test "auto created variables have correct alignment" {
794 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
795 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
796
797 const S = struct {
798 fn foo(str: [*]const u8) u32 {
799 for (@as([*]align(1) const u32, @ptrCast(str))[0..1]) |v| {
800 return v;
801 }
802 return 0;
803 }
804 };
805 try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
806 comptime assert(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
807}
808
809test "extern variable with non-pointer opaque type" {
810 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
811 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
812 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
815
816 @export(&var_to_export, .{ .name = "opaque_extern_var" });
817 try expect(@as(*align(1) u32, @ptrCast(&opaque_extern_var)).* == 42);
818}
819extern var opaque_extern_var: opaque {};
820var var_to_export: u32 = 42;
821
822test "lazy typeInfo value as generic parameter" {
823 const S = struct {
824 fn foo(args: anytype) void {
825 _ = args;
826 }
827 };
828 S.foo(@typeInfo(@TypeOf(.{})));
829}
830
831test "variable name containing underscores does not shadow int primitive" {
832 const _u0 = 0;
833 const i_8 = 0;
834 const u16_ = 0;
835 const i3_2 = 0;
836 const u6__4 = 0;
837 const i2_04_8 = 0;
838
839 _ = _u0;
840 _ = i_8;
841 _ = u16_;
842 _ = i3_2;
843 _ = u6__4;
844 _ = i2_04_8;
845}
846
847test "if expression type coercion" {
848 var cond: bool = true;
849 _ = &cond;
850 const x: u16 = if (cond) 1 else 0;
851 try expect(@as(u16, x) == 1);
852}
853
854test "discarding the result of various expressions" {
855 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
856 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
857
858 const S = struct {
859 fn foo() !u32 {
860 return 1;
861 }
862 fn bar() ?u32 {
863 return 1;
864 }
865 };
866 _ = S.bar() orelse {
867 // do nothing
868 };
869 _ = S.foo() catch {
870 // do nothing
871 };
872 _ = switch (1) {
873 1 => 1,
874 2 => {},
875 else => return,
876 };
877 _ = try S.foo();
878 _ = if (S.bar()) |some| some else {};
879 _ = blk: {
880 if (S.bar()) |some| break :blk some;
881 break :blk;
882 };
883 _ = while (S.bar()) |some| break some else {};
884 _ = for ("foo") |char| break char else {};
885}
886
887test "labeled block implicitly ends in a break" {
888 var a = false;
889 _ = &a;
890 blk: {
891 if (a) break :blk;
892 }
893}
894
895test "catch in block has correct result location" {
896 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
897
898 const S = struct {
899 fn open() error{A}!@This() {
900 return @This(){};
901 }
902 fn foo(_: @This()) u32 {
903 return 1;
904 }
905 };
906 const config_h_text: u32 = blk: {
907 var dir = S.open() catch unreachable;
908 break :blk dir.foo();
909 };
910 try expect(config_h_text == 1);
911}
912
913test "labeled block with runtime branch forwards its result location type to break statements" {
914 const E = enum { a, b };
915 var a = false;
916 _ = &a;
917 const e: E = blk: {
918 if (a) {
919 break :blk .a;
920 }
921 break :blk .b;
922 };
923 try expect(e == .b);
924}
925
926test "try in labeled block doesn't cast to wrong type" {
927 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
928
929 const S = struct {
930 a: u32,
931 fn foo() anyerror!u32 {
932 return 1;
933 }
934 };
935 const s: ?*S = blk: {
936 var a = try S.foo();
937 _ = &a;
938 break :blk null;
939 };
940 _ = s;
941}
942
943test "vector initialized with array init syntax has proper type" {
944 comptime {
945 const actual = -@Vector(4, i32){ 1, 2, 3, 4 };
946 try std.testing.expectEqual(@Vector(4, i32){ -1, -2, -3, -4 }, actual);
947 }
948}
949
950test "weird array and tuple initializations" {
951 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
952 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
953
954 const E = enum { a, b };
955 const S = struct { e: E };
956 var a = false;
957 _ = &a;
958 const b = S{ .e = .a };
959
960 _ = &[_]S{
961 if (a) .{ .e = .a } else .{ .e = .b },
962 };
963
964 if (true) return error.SkipZigTest;
965
966 const S2 = @TypeOf(.{ false, b });
967 _ = &S2{
968 true,
969 if (a) .{ .e = .a } else .{ .e = .b },
970 };
971 const S3 = @TypeOf(.{ .a = false, .b = b });
972 _ = &S3{
973 .a = true,
974 .b = if (a) .{ .e = .a } else .{ .e = .b },
975 };
976}
977
978test "array type comes from generic function" {
979 const S = struct {
980 fn A() type {
981 return struct { a: u8 = 0 };
982 }
983 };
984 const args = [_]S.A(){.{}};
985 _ = args;
986}
987
988test "generic function uses return type of other generic function" {
989 if (true) {
990 // This test has been failing sporadically on the CI.
991 // It's not enough to verify that it works locally; we need to diagnose why
992 // it fails on the CI sometimes before turning it back on.
993 // https://github.com/ziglang/zig/issues/12208
994 return error.SkipZigTest;
995 }
996
997 const S = struct {
998 fn call(
999 f: anytype,
1000 args: anytype,
1001 ) @TypeOf(@call(.auto, f, @as(@TypeOf(args), undefined))) {
1002 return @call(.auto, f, args);
1003 }
1004
1005 fn func(arg: anytype) @TypeOf(arg) {
1006 return arg;
1007 }
1008 };
1009 try std.testing.expect(S.call(S.func, .{@as(u8, 1)}) == 1);
1010}
1011
1012test "const alloc with comptime-known initializer is made comptime-known" {
1013 const S = struct {
1014 a: bool,
1015 b: [2]u8,
1016 };
1017 {
1018 const s: S = .{
1019 .a = false,
1020 .b = .{ 1, 2 },
1021 };
1022 if (s.a) @compileError("bad");
1023 }
1024 {
1025 const s: S = .{
1026 .a = false,
1027 .b = [2]u8{ 1, 2 },
1028 };
1029 if (s.a) @compileError("bad");
1030 }
1031 {
1032 const s: S = comptime .{
1033 .a = false,
1034 .b = .{ 1, 2 },
1035 };
1036 if (s.a) @compileError("bad");
1037 }
1038 {
1039 const Const = struct {
1040 limbs: []const usize,
1041 positive: bool,
1042 };
1043 const biggest: Const = .{
1044 .limbs = &([1]usize{comptime std.math.maxInt(usize)} ** 128),
1045 .positive = false,
1046 };
1047 if (biggest.positive) @compileError("bad");
1048 }
1049 {
1050 const U = union(enum) {
1051 a: usize,
1052 };
1053 const u: U = .{
1054 .a = comptime std.math.maxInt(usize),
1055 };
1056 if (u.a == 0) @compileError("bad");
1057 }
1058}
1059
1060comptime {
1061 // coerce result ptr outside a function
1062 const S = struct { a: comptime_int };
1063 var s: S = undefined;
1064 s = S{ .a = 1 };
1065 assert(s.a == 1);
1066}
1067
1068test "switch inside @as gets correct type" {
1069 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1070
1071 var a: u32 = 0;
1072 _ = &a;
1073 var b: [2]u32 = undefined;
1074 b[0] = @as(u32, switch (a) {
1075 1 => 1,
1076 else => 0,
1077 });
1078}
1079
1080test "inline call of function with a switch inside the return statement" {
1081 const S = struct {
1082 inline fn foo(x: anytype) @TypeOf(x) {
1083 return switch (x) {
1084 1 => 1,
1085 else => unreachable,
1086 };
1087 }
1088 };
1089 try expect(S.foo(1) == 1);
1090}
1091
1092test "pointer to zero sized global is mutable" {
1093 const S = struct {
1094 const Thing = struct {};
1095
1096 var thing: Thing = undefined;
1097 };
1098 try expect(@TypeOf(&S.thing) == *S.Thing);
1099}
1100
1101test "returning an opaque type from a function" {
1102 const S = struct {
1103 fn foo(comptime a: u32) type {
1104 return opaque {
1105 const b = a;
1106 };
1107 }
1108 };
1109 try expect(S.foo(123).b == 123);
1110}
1111
1112test "orelse coercion as function argument" {
1113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1114
1115 const Loc = struct { start: i32 = -1 };
1116 const Container = struct {
1117 a: ?Loc = null,
1118 fn init(a: Loc) @This() {
1119 return .{
1120 .a = a,
1121 };
1122 }
1123 };
1124 var optional: ?Loc = .{};
1125 _ = &optional;
1126 const foo = Container.init(optional orelse .{});
1127 try expect(foo.a.?.start == -1);
1128}
1129
1130test "runtime-known globals initialized with undefined" {
1131 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1132
1133 const S = struct {
1134 var array: [10]u32 = [_]u32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1135 var vp: [*]u32 = undefined;
1136 var s: []u32 = undefined;
1137 };
1138
1139 S.vp = &S.array;
1140 S.s = S.vp[0..5];
1141
1142 try expect(S.s[0] == 1);
1143 try expect(S.s[4] == 5);
1144}
1145
1146test "arrays and vectors with big integers" {
1147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1148 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1150 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1153 if (builtin.zig_backend == .stage2_llvm and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23805
1154
1155 inline for (.{ u65528, u65529, u65535 }) |Int| {
1156 var a: [1]Int = undefined;
1157 a[0] = std.math.maxInt(Int);
1158 try expect(a[0] == comptime std.math.maxInt(Int));
1159 var b: @Vector(1, Int) = undefined;
1160 b[0] = std.math.maxInt(Int);
1161 try expect(b[0] == comptime std.math.maxInt(Int));
1162 }
1163}
1164
1165test "pointer to struct literal with runtime field is constant" {
1166 const S = struct { data: usize };
1167 var runtime_zero: usize = 0;
1168 _ = &runtime_zero;
1169 const ptr = &S{ .data = runtime_zero };
1170 try expect(@typeInfo(@TypeOf(ptr)).pointer.is_const);
1171}
1172
1173fn testSignedCmp(comptime T: type) !void {
1174 var z: T = 0;
1175 var p: T = 123;
1176 var n: T = -123;
1177 var min: T = std.math.minInt(T);
1178 var max: T = std.math.maxInt(T);
1179 var half_min: T = std.math.minInt(T) / 2;
1180 var half_max: T = std.math.minInt(T) / 2;
1181 _ = .{ &z, &p, &n, &min, &max, &half_min, &half_max };
1182 try expect(z == z and z != p and z != n);
1183 try expect(p == p and p != n and n == n);
1184 try expect(z > n and z < p and z >= n and z <= p);
1185 try expect(!(z < n or z > p or z <= n or z >= p or z > z or z < z));
1186 try expect(p > n and n < p and p >= n and n <= p and p >= p and p <= p and n >= n and n <= n);
1187 try expect(!(p < n or n > p or p <= n or n >= p or p > p or p < p or n > n or n < n));
1188 try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p and 0 != n);
1189 try expect(z > -123 and p > -123 and !(n > 123));
1190 try expect(z < 123 and !(p < 123) and n < 123);
1191 try expect(-123 <= z and -123 <= p and -123 <= n);
1192 try expect(123 >= z and 123 >= p and 123 >= n);
1193 try expect(!(0 != z or 123 != p or -123 != n));
1194 try expect(!(z > 0 or -123 > p or 123 < n));
1195
1196 try expect(min <= max and z <= max and p <= max and n <= max and half_max <= max and half_min <= max);
1197 try expect(min <= max and min <= z and min <= p and min <= n and min <= half_min and min <= half_max);
1198}
1199
1200fn testUnsignedCmp(comptime T: type) !void {
1201 var z: T = 0;
1202 var p: T = 123;
1203 var max: T = std.math.maxInt(T);
1204 var half_max: T = std.math.minInt(T) / 2;
1205 _ = .{ &z, &p, &max, &half_max };
1206 try expect(z == z and z != p);
1207 try expect(p == p);
1208 try expect(z < p and z <= p);
1209 try expect(!(z > p or z >= p or z > z or z < z));
1210 try expect(p >= p and p <= p);
1211 try expect(!(p > p or p < p));
1212 try expect(z == 0 and z != 123 and z != -123 and 0 == z and 0 != p);
1213 try expect(z > -123 and p > -123);
1214 try expect(z < 123 and !(p < 123));
1215 try expect(-123 <= z and -123 <= p);
1216 try expect(123 >= z and 123 >= p);
1217 try expect(!(0 != z or 123 != p));
1218 try expect(!(z > 0 or -123 > p));
1219
1220 try expect(z <= max and p <= max and half_max <= max);
1221 try expect(half_max != max);
1222}
1223
1224test "integer compare <= 64 bits" {
1225 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1226
1227 inline for (.{ u8, u16, u32, u64, usize, u10, u20, u30, u60 }) |T| {
1228 try testUnsignedCmp(T);
1229 try comptime testUnsignedCmp(T);
1230 }
1231 inline for (.{ i8, i16, i32, i64, isize, i10, i20, i30, i60 }) |T| {
1232 try testSignedCmp(T);
1233 try comptime testSignedCmp(T);
1234 }
1235}
1236
1237test "integer compare <= 128 bits" {
1238 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1240
1241 inline for (.{ u65, u96, u127, u128 }) |T| {
1242 try testUnsignedCmp(T);
1243 try comptime testUnsignedCmp(T);
1244 }
1245 inline for (.{ i65, i96, i127, i128 }) |T| {
1246 try testSignedCmp(T);
1247 try comptime testSignedCmp(T);
1248 }
1249}
1250
1251test "reference to inferred local variable works as expected" {
1252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1253
1254 const Crasher = struct {
1255 lets_crash: u64 = 0,
1256 };
1257
1258 var a: Crasher = undefined;
1259 const crasher_ptr = &a;
1260 var crasher_local = crasher_ptr.*;
1261 const crasher_local_ptr = &crasher_local;
1262 crasher_local_ptr.lets_crash = 1;
1263
1264 try expect(crasher_local.lets_crash != a.lets_crash);
1265}
1266
1267test "@Int returned from block" {
1268 const T = comptime b: {
1269 break :b @Int(.unsigned, 8);
1270 };
1271 try std.testing.expect(T == u8);
1272}
1273
1274test "comptime variable initialized with addresses of literals" {
1275 comptime var st = .{
1276 .foo = &1,
1277 .bar = &2,
1278 };
1279 _ = &st;
1280
1281 inline for (@typeInfo(@TypeOf(st)).@"struct".fields) |field| {
1282 _ = field;
1283 }
1284}
1285
1286test "pointer to tuple field can be dereferenced at comptime" {
1287 comptime {
1288 const tuple_with_ptrs = .{ &0, &0 };
1289 const field_ptr = (&tuple_with_ptrs.@"0");
1290 _ = field_ptr.*;
1291 }
1292}
1293
1294test "proper value is returned from labeled block" {
1295 const S = struct {
1296 fn hash(v: *u32, key: anytype) void {
1297 const Key = @TypeOf(key);
1298 if (@typeInfo(Key) == .error_set) {
1299 v.* += 1;
1300 return;
1301 }
1302 switch (@typeInfo(Key)) {
1303 .error_union => blk: {
1304 const payload = key catch |err| {
1305 hash(v, err);
1306 break :blk;
1307 };
1308
1309 hash(v, payload);
1310 },
1311
1312 else => unreachable,
1313 }
1314 }
1315 };
1316 const g: error{Test}!void = error.Test;
1317
1318 var v: u32 = 0;
1319 S.hash(&v, g);
1320 try expect(v == 1);
1321}
1322
1323test "const inferred array of slices" {
1324 const T = struct { v: bool };
1325
1326 const decls = [_][]const T{
1327 &[_]T{
1328 .{ .v = false },
1329 },
1330 };
1331 _ = decls;
1332}
1333
1334test "var inferred array of slices" {
1335 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1336
1337 const T = struct { v: bool };
1338
1339 var decls = [_][]const T{
1340 &[_]T{
1341 .{ .v = false },
1342 },
1343 };
1344 _ = &decls;
1345}
1346
1347test "copy array of self-referential struct" {
1348 const ListNode = struct {
1349 next: ?*const @This() = null,
1350 };
1351 comptime var nodes = [_]ListNode{ .{}, .{} };
1352 nodes[0].next = &nodes[1];
1353 const copied_nodes = nodes;
1354 _ = copied_nodes;
1355}
1356
1357test "break out of block based on comptime known values" {
1358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1360
1361 const S = struct {
1362 const source = "A-";
1363
1364 fn parseNote() ?i32 {
1365 const letter = source[0];
1366 const modifier = source[1];
1367
1368 const semitone = blk: {
1369 if (letter == 'C' and modifier == '-') break :blk @as(i32, 0);
1370 if (letter == 'C' and modifier == '#') break :blk @as(i32, 1);
1371 if (letter == 'D' and modifier == '-') break :blk @as(i32, 2);
1372 if (letter == 'D' and modifier == '#') break :blk @as(i32, 3);
1373 if (letter == 'E' and modifier == '-') break :blk @as(i32, 4);
1374 if (letter == 'F' and modifier == '-') break :blk @as(i32, 5);
1375 if (letter == 'F' and modifier == '#') break :blk @as(i32, 6);
1376 if (letter == 'G' and modifier == '-') break :blk @as(i32, 7);
1377 if (letter == 'G' and modifier == '#') break :blk @as(i32, 8);
1378 if (letter == 'A' and modifier == '-') break :blk @as(i32, 9);
1379 if (letter == 'A' and modifier == '#') break :blk @as(i32, 10);
1380 if (letter == 'B' and modifier == '-') break :blk @as(i32, 11);
1381 return null;
1382 };
1383
1384 return semitone;
1385 }
1386 };
1387 const result = S.parseNote();
1388 try std.testing.expect(result.? == 9);
1389}
1390
1391test "allocation and looping over 3-byte integer" {
1392 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1393 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1395 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1396 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1397
1398 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag.isDarwin()) {
1399 return error.SkipZigTest; // TODO
1400 }
1401 if (builtin.cpu.arch == .s390x and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO
1402
1403 try expect(@sizeOf(u24) == 4);
1404 try expect(@sizeOf([1]u24) == 4);
1405 try expect(@alignOf(u24) == 4);
1406 try expect(@alignOf([1]u24) == 4);
1407
1408 var x = try std.testing.allocator.alloc(u24, 2);
1409 defer std.testing.allocator.free(x);
1410 try expect(x.len == 2);
1411 x[0] = 0xFFFFFF;
1412 x[1] = 0xFFFFFF;
1413
1414 const bytes = std.mem.sliceAsBytes(x);
1415 try expect(@TypeOf(bytes) == []align(4) u8);
1416 try expect(bytes.len == 8);
1417
1418 for (bytes) |*b| {
1419 b.* = 0x00;
1420 }
1421
1422 try expect(x[0] == 0x00);
1423 try expect(x[1] == 0x00);
1424}
1425
1426test "loading array from struct is not optimized away" {
1427 const S = struct {
1428 arr: [1]u32 = .{0},
1429 fn doTheTest(self: *@This()) !void {
1430 const o = self.arr;
1431 self.arr[0] = 1;
1432 try expect(o[0] == 0);
1433 }
1434 };
1435 var s = S{};
1436 try s.doTheTest();
1437}