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