master
1const std = @import("std");
2const builtin = @import("builtin");
3const native_endian = builtin.target.cpu.arch.endian();
4const assert = std.debug.assert;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7const expectEqualSlices = std.testing.expectEqualSlices;
8const maxInt = std.math.maxInt;
9
10top_level_field: i32,
11
12test "top level fields" {
13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14
15 var instance = @This(){
16 .top_level_field = 1234,
17 };
18 instance.top_level_field += 1;
19 try expect(@as(i32, 1235) == instance.top_level_field);
20}
21
22const StructWithFields = struct {
23 a: u8,
24 b: u32,
25 c: u64,
26 d: u32,
27
28 fn first(self: *const StructWithFields) u8 {
29 return self.a;
30 }
31
32 fn second(self: *const StructWithFields) u32 {
33 return self.b;
34 }
35
36 fn third(self: *const StructWithFields) u64 {
37 return self.c;
38 }
39
40 fn fourth(self: *const StructWithFields) u32 {
41 return self.d;
42 }
43};
44
45test "non-packed struct has fields padded out to the required alignment" {
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
47
48 const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 };
49 try expect(foo.first() == 5);
50 try expect(foo.second() == 1);
51 try expect(foo.third() == 10);
52 try expect(foo.fourth() == 2);
53}
54
55const SmallStruct = struct {
56 a: u8,
57 b: u8,
58
59 fn first(self: *SmallStruct) u8 {
60 return self.a;
61 }
62
63 fn second(self: *SmallStruct) u8 {
64 return self.b;
65 }
66};
67
68test "lower unnamed constants" {
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70
71 var foo = SmallStruct{ .a = 1, .b = 255 };
72 try expect(foo.first() == 1);
73 try expect(foo.second() == 255);
74}
75
76const StructWithNoFields = struct {
77 fn add(a: i32, b: i32) i32 {
78 return a + b;
79 }
80};
81
82const StructFoo = struct {
83 a: i32,
84 b: bool,
85 c: u64,
86};
87
88test "structs" {
89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
90 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
91 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
92
93 var foo: StructFoo = undefined;
94 @memset(@as([*]u8, @ptrCast(&foo))[0..@sizeOf(StructFoo)], 0);
95 foo.a += 1;
96 foo.b = foo.a == 1;
97 try testFoo(foo);
98 testMutation(&foo);
99 try expect(foo.c == 100);
100}
101fn testFoo(foo: StructFoo) !void {
102 try expect(foo.b);
103}
104fn testMutation(foo: *StructFoo) void {
105 foo.c = 100;
106}
107
108test "struct byval assign" {
109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
110
111 var foo1: StructFoo = undefined;
112 var foo2: StructFoo = undefined;
113
114 foo1.a = 1234;
115 foo2.a = 0;
116 try expect(foo2.a == 0);
117 foo2 = foo1;
118 try expect(foo2.a == 1234);
119}
120
121test "call struct static method" {
122 const result = StructWithNoFields.add(3, 4);
123 try expect(result == 7);
124}
125
126const should_be_11 = StructWithNoFields.add(5, 6);
127
128test "invoke static method in global scope" {
129 try expect(should_be_11 == 11);
130}
131
132const empty_global_instance = StructWithNoFields{};
133
134test "return empty struct instance" {
135 _ = returnEmptyStructInstance();
136}
137fn returnEmptyStructInstance() StructWithNoFields {
138 return empty_global_instance;
139}
140
141test "fn call of struct field" {
142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
143
144 const Foo = struct {
145 ptr: fn () i32,
146 };
147 const S = struct {
148 fn aFunc() i32 {
149 return 13;
150 }
151
152 fn callStructField(comptime foo: Foo) i32 {
153 return foo.ptr();
154 }
155 };
156
157 try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
158}
159
160test "struct initializer" {
161 const val = Val{ .x = 42 };
162 try expect(val.x == 42);
163}
164
165const MemberFnTestFoo = struct {
166 x: i32,
167 fn member(foo: MemberFnTestFoo) i32 {
168 return foo.x;
169 }
170};
171
172test "call member function directly" {
173 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
174
175 const instance = MemberFnTestFoo{ .x = 1234 };
176 const result = MemberFnTestFoo.member(instance);
177 try expect(result == 1234);
178}
179
180test "store member function in variable" {
181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
182
183 const instance = MemberFnTestFoo{ .x = 1234 };
184 const memberFn = MemberFnTestFoo.member;
185 const result = memberFn(instance);
186 try expect(result == 1234);
187}
188
189test "member functions" {
190 const r = MemberFnRand{ .seed = 1234 };
191 try expect(r.getSeed() == 1234);
192}
193const MemberFnRand = struct {
194 seed: u32,
195 pub fn getSeed(r: *const MemberFnRand) u32 {
196 return r.seed;
197 }
198};
199
200test "return struct byval from function" {
201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
202
203 const Bar = struct {
204 x: i32,
205 y: i32,
206 fn makeBar2(x: i32, y: i32) @This() {
207 return .{
208 .x = x,
209 .y = y,
210 };
211 }
212 };
213 const bar = Bar.makeBar2(1234, 5678);
214 try expect(bar.y == 5678);
215}
216
217test "call method with mutable reference to struct with no fields" {
218 const S = struct {
219 fn doC(s: *const @This()) bool {
220 _ = s;
221 return true;
222 }
223 fn do(s: *@This()) bool {
224 _ = s;
225 return true;
226 }
227 };
228
229 var s = S{};
230 try expect(S.doC(&s));
231 try expect(s.doC());
232 try expect(S.do(&s));
233 try expect(s.do());
234}
235
236test "struct field init with catch" {
237 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
238
239 const S = struct {
240 fn doTheTest() !void {
241 var x: anyerror!isize = 1;
242 _ = &x;
243 const req = Foo{
244 .field = x catch undefined,
245 };
246 try expect(req.field == 1);
247 }
248
249 pub const Foo = extern struct {
250 field: isize,
251 };
252 };
253 try S.doTheTest();
254 try comptime S.doTheTest();
255}
256
257const blah: packed struct {
258 a: u3,
259 b: u3,
260 c: u2,
261} = undefined;
262
263test "bit field alignment" {
264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
265
266 try expect(@TypeOf(&blah.b) == *align(1:3:1) const u3);
267}
268
269const Node = struct {
270 val: Val,
271 next: *Node,
272};
273
274const Val = struct {
275 x: i32,
276};
277
278test "struct point to self" {
279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
280 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
281
282 var root: Node = undefined;
283 root.val.x = 1;
284
285 var node: Node = undefined;
286 node.next = &root;
287 node.val.x = 2;
288
289 root.next = &node;
290
291 try expect(node.next.next.next.val.x == 1);
292}
293
294test "void struct fields" {
295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
296
297 const foo = VoidStructFieldsFoo{
298 .a = void{},
299 .b = 1,
300 .c = void{},
301 };
302 try expect(foo.b == 1);
303 try expect(@sizeOf(VoidStructFieldsFoo) == 4);
304}
305const VoidStructFieldsFoo = struct {
306 a: void,
307 b: i32,
308 c: void,
309};
310
311test "return empty struct from fn" {
312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
313
314 _ = testReturnEmptyStructFromFn();
315}
316const EmptyStruct2 = struct {};
317fn testReturnEmptyStructFromFn() EmptyStruct2 {
318 return EmptyStruct2{};
319}
320
321test "pass slice of empty struct to fn" {
322 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
323 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
324
325 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
326}
327fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
328 return slice.len;
329}
330
331test "self-referencing struct via array member" {
332 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
333 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
334 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
335
336 const T = struct {
337 children: [1]*@This(),
338 };
339 var x: T = undefined;
340 x = T{ .children = .{&x} };
341 try expect(x.children[0] == &x);
342}
343
344test "empty struct method call" {
345 const es = EmptyStruct{};
346 try expect(es.method() == 1234);
347}
348const EmptyStruct = struct {
349 fn method(es: *const EmptyStruct) i32 {
350 _ = es;
351 return 1234;
352 }
353};
354
355test "align 1 field before self referential align 8 field as slice return type" {
356 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
358 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
359
360 const result = alloc(Expr);
361 try expect(result.len == 0);
362}
363
364const Expr = union(enum) {
365 Literal: u8,
366 Question: *Expr,
367};
368
369fn alloc(comptime T: type) []T {
370 return &[_]T{};
371}
372
373const APackedStruct = packed struct {
374 x: u8,
375 y: u8,
376};
377
378test "packed struct" {
379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
383
384 var foo = APackedStruct{
385 .x = 1,
386 .y = 2,
387 };
388 foo.y += 1;
389 const four = foo.x + foo.y;
390 try expect(four == 4);
391}
392
393const Foo24Bits = packed struct {
394 field: u24,
395};
396const Foo96Bits = packed struct {
397 a: u24,
398 b: u24,
399 c: u24,
400 d: u24,
401};
402
403test "packed struct 24bits" {
404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
407 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
409 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
410
411 comptime {
412 std.debug.assert(@sizeOf(Foo24Bits) == @sizeOf(u24));
413 std.debug.assert(@sizeOf(Foo96Bits) == @sizeOf(u96));
414 }
415
416 var value = Foo96Bits{
417 .a = 0,
418 .b = 0,
419 .c = 0,
420 .d = 0,
421 };
422 value.a += 1;
423 try expect(value.a == 1);
424 try expect(value.b == 0);
425 try expect(value.c == 0);
426 try expect(value.d == 0);
427
428 value.b += 1;
429 try expect(value.a == 1);
430 try expect(value.b == 1);
431 try expect(value.c == 0);
432 try expect(value.d == 0);
433
434 value.c += 1;
435 try expect(value.a == 1);
436 try expect(value.b == 1);
437 try expect(value.c == 1);
438 try expect(value.d == 0);
439
440 value.d += 1;
441 try expect(value.a == 1);
442 try expect(value.b == 1);
443 try expect(value.c == 1);
444 try expect(value.d == 1);
445}
446
447test "runtime struct initialization of bitfield" {
448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
453
454 const s1 = Nibbles{
455 .x = x1,
456 .y = x1,
457 };
458 const s2 = Nibbles{
459 .x = @as(u4, @intCast(x2)),
460 .y = @as(u4, @intCast(x2)),
461 };
462
463 try expect(s1.x == x1);
464 try expect(s1.y == x1);
465 try expect(s2.x == @as(u4, @intCast(x2)));
466 try expect(s2.y == @as(u4, @intCast(x2)));
467}
468
469var x1 = @as(u4, 1);
470var x2 = @as(u8, 2);
471
472const Nibbles = packed struct {
473 x: u4,
474 y: u4,
475};
476
477const Bitfields = packed struct {
478 f1: u16,
479 f2: u16,
480 f3: u8,
481 f4: u8,
482 f5: u4,
483 f6: u4,
484 f7: u8,
485};
486
487test "packed struct fields are ordered from LSB to MSB" {
488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
492
493 var all: u64 = 0x7765443322221111;
494 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
495 @memcpy(bytes[0..8], @as([*]u8, @ptrCast(&all)));
496 const bitfields = @as(*Bitfields, @ptrCast(&bytes)).*;
497
498 try expect(bitfields.f1 == 0x1111);
499 try expect(bitfields.f2 == 0x2222);
500 try expect(bitfields.f3 == 0x33);
501 try expect(bitfields.f4 == 0x44);
502 try expect(bitfields.f5 == 0x5);
503 try expect(bitfields.f6 == 0x6);
504 try expect(bitfields.f7 == 0x77);
505}
506
507test "implicit cast packed struct field to const ptr" {
508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
509 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
511 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
512 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
513
514 const LevelUpMove = packed struct {
515 move_id: u9,
516 level: u7,
517
518 fn toInt(value: u7) u7 {
519 return value;
520 }
521 };
522
523 var lup: LevelUpMove = undefined;
524 lup.level = 12;
525 const res = LevelUpMove.toInt(lup.level);
526 try expect(res == 12);
527}
528
529test "zero-bit field in packed struct" {
530 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
531
532 const S = packed struct {
533 x: u10,
534 y: void,
535 };
536 var x: S = undefined;
537 _ = &x;
538}
539
540test "packed struct with non-ABI-aligned field" {
541 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
542 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
543 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
547 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
548
549 const S = packed struct {
550 x: u9,
551 y: u183,
552 };
553 var s: S = undefined;
554 s.x = 1;
555 s.y = 42;
556 try expect(s.x == 1);
557 try expect(s.y == 42);
558}
559
560const BitField1 = packed struct {
561 a: u3,
562 b: u3,
563 c: u2,
564};
565
566const bit_field_1 = BitField1{
567 .a = 1,
568 .b = 2,
569 .c = 3,
570};
571
572test "bit field access" {
573 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
577 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
578
579 var data = bit_field_1;
580 try expect(getA(&data) == 1);
581 try expect(getB(&data) == 2);
582 try expect(getC(&data) == 3);
583 comptime assert(@sizeOf(BitField1) == 1);
584
585 data.b += 1;
586 try expect(data.b == 3);
587
588 data.a += 1;
589 try expect(data.a == 2);
590 try expect(data.b == 3);
591}
592
593fn getA(data: *const BitField1) u3 {
594 return data.a;
595}
596
597fn getB(data: *const BitField1) u3 {
598 return data.b;
599}
600
601fn getC(data: *const BitField1) u2 {
602 return data.c;
603}
604
605test "default struct initialization fields" {
606 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
607
608 const S = struct {
609 a: i32 = 1234,
610 b: i32,
611 };
612 const x = S{
613 .b = 5,
614 };
615 var five: i32 = 5;
616 _ = &five;
617 const y = S{
618 .b = five,
619 };
620 if (x.a + x.b != 1239) {
621 @compileError("it should be comptime-known");
622 }
623 try expect(y.a == x.a);
624 try expect(y.b == x.b);
625 try expect(1239 == x.a + x.b);
626}
627
628test "packed array 24bits" {
629 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
630 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
632 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
633
634 comptime {
635 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
636 try expect(@sizeOf(FooArray24Bits) == @sizeOf(u96));
637 }
638
639 var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
640 bytes[bytes.len - 1] = 0xbb;
641 const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
642 try expect(ptr.a == 0);
643 try expect(ptr.b0.field == 0);
644 try expect(ptr.b1.field == 0);
645 try expect(ptr.c == 0);
646
647 ptr.a = maxInt(u16);
648 try expect(ptr.a == maxInt(u16));
649 try expect(ptr.b0.field == 0);
650 try expect(ptr.b1.field == 0);
651 try expect(ptr.c == 0);
652
653 ptr.b0.field = maxInt(u24);
654 try expect(ptr.a == maxInt(u16));
655 try expect(ptr.b0.field == maxInt(u24));
656 try expect(ptr.b1.field == 0);
657 try expect(ptr.c == 0);
658
659 ptr.b1.field = maxInt(u24);
660 try expect(ptr.a == maxInt(u16));
661 try expect(ptr.b0.field == maxInt(u24));
662 try expect(ptr.b1.field == maxInt(u24));
663 try expect(ptr.c == 0);
664
665 ptr.c = maxInt(u16);
666 try expect(ptr.a == maxInt(u16));
667 try expect(ptr.b0.field == maxInt(u24));
668 try expect(ptr.b1.field == maxInt(u24));
669 try expect(ptr.c == maxInt(u16));
670
671 try expect(bytes[bytes.len - 1] == 0xbb);
672}
673
674const Foo32Bits = packed struct {
675 field: u24,
676 pad: u8,
677};
678
679const FooArray24Bits = packed struct {
680 a: u16,
681 b0: Foo32Bits,
682 b1: Foo32Bits,
683 c: u16,
684};
685
686const FooStructAligned = packed struct {
687 a: u8,
688 b: u8,
689};
690
691const FooArrayOfAligned = packed struct {
692 a: [2]FooStructAligned,
693};
694
695test "pointer to packed struct member in a stack variable" {
696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
697 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
698 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
700 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
701
702 const S = packed struct {
703 a: u2,
704 b: u2,
705 };
706
707 var s = S{ .a = 2, .b = 0 };
708 const b_ptr = &s.b;
709 try expect(s.b == 0);
710 b_ptr.* = 2;
711 try expect(s.b == 2);
712}
713
714test "packed struct with u0 field access" {
715 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
716
717 const S = packed struct {
718 f0: u0,
719 };
720 var s = S{ .f0 = 0 };
721 _ = &s;
722 comptime assert(s.f0 == 0);
723}
724
725test "access to global struct fields" {
726 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
727
728 g_foo.bar.value = 42;
729 try expect(g_foo.bar.value == 42);
730}
731
732const S0 = struct {
733 bar: S1,
734
735 pub const S1 = struct {
736 value: u8,
737 };
738
739 fn init() @This() {
740 return S0{ .bar = S1{ .value = 123 } };
741 }
742};
743
744var g_foo: S0 = S0.init();
745
746test "packed struct with fp fields" {
747 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
748 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
749 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
750 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
751 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
752
753 const S = packed struct {
754 data0: f32,
755 data1: f32,
756 data2: f32,
757
758 pub fn frob(self: *@This()) void {
759 self.data0 += self.data1 + self.data2;
760 self.data1 += self.data0 + self.data2;
761 self.data2 += self.data0 + self.data1;
762 }
763 };
764
765 var s: S = undefined;
766 s.data0 = 1.0;
767 s.data1 = 2.0;
768 s.data2 = 3.0;
769 s.frob();
770 try expect(@as(f32, 6.0) == s.data0);
771 try expect(@as(f32, 11.0) == s.data1);
772 try expect(@as(f32, 20.0) == s.data2);
773}
774
775test "fn with C calling convention returns struct by value" {
776 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
777 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
778
779 const S = struct {
780 fn entry() !void {
781 const x = makeBar(10);
782 try expect(@as(i32, 10) == x.handle);
783 }
784
785 const ExternBar = extern struct {
786 handle: i32,
787 };
788
789 fn makeBar(t: i32) callconv(.c) ExternBar {
790 return ExternBar{
791 .handle = t,
792 };
793 }
794 };
795 try S.entry();
796 try comptime S.entry();
797}
798
799test "non-packed struct with u128 entry in union" {
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;
803 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
804 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
805
806 const U = union(enum) {
807 Num: u128,
808 Void,
809 };
810
811 const S = struct {
812 f1: U,
813 f2: U,
814 };
815
816 var sx: S = undefined;
817 var s = &sx;
818 try expect(@intFromPtr(&s.f2) - @intFromPtr(&s.f1) == @offsetOf(S, "f2"));
819 var v2 = U{ .Num = 123 };
820 _ = &v2;
821 s.f2 = v2;
822 try expect(s.f2.Num == 123);
823}
824
825test "packed struct field passed to generic function" {
826 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
828 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
830
831 const S = struct {
832 const P = packed struct {
833 b: u5,
834 g: u5,
835 r: u5,
836 a: u1,
837 };
838
839 fn genericReadPackedField(ptr: anytype) u5 {
840 return ptr.*;
841 }
842 };
843
844 var p: S.P = undefined;
845 p.b = 29;
846 const loaded = S.genericReadPackedField(&p.b);
847 try expect(loaded == 29);
848}
849
850test "anonymous struct literal syntax" {
851 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
852
853 const S = struct {
854 const Point = struct {
855 x: i32,
856 y: i32,
857 };
858
859 fn doTheTest() !void {
860 var p: Point = .{
861 .x = 1,
862 .y = 2,
863 };
864 _ = &p;
865 try expect(p.x == 1);
866 try expect(p.y == 2);
867 }
868 };
869 try S.doTheTest();
870 try comptime S.doTheTest();
871}
872
873test "fully anonymous struct" {
874 const S = struct {
875 fn doTheTest() !void {
876 try dump(.{
877 .int = @as(u32, 1234),
878 .float = @as(f64, 12.34),
879 .b = true,
880 .s = "hi",
881 });
882 }
883 fn dump(args: anytype) !void {
884 try expect(args.int == 1234);
885 try expect(args.float == 12.34);
886 try expect(args.b);
887 try expect(args.s[0] == 'h');
888 try expect(args.s[1] == 'i');
889 }
890 };
891 try S.doTheTest();
892 try comptime S.doTheTest();
893}
894
895test "fully anonymous list literal" {
896 const S = struct {
897 fn doTheTest() !void {
898 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
899 }
900 fn dump(args: anytype) !void {
901 try expect(args.@"0" == 1234);
902 try expect(args.@"1" == 12.34);
903 try expect(args.@"2");
904 try expect(args.@"3"[0] == 'h');
905 try expect(args.@"3"[1] == 'i');
906 }
907 };
908 try S.doTheTest();
909 try comptime S.doTheTest();
910}
911
912test "tuple assigned to variable" {
913 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
914 _ = &vec;
915 try expect(vec.@"0" == 22);
916 try expect(vec.@"1" == 55);
917 try expect(vec.@"2" == 99);
918 try expect(vec[0] == 22);
919 try expect(vec[1] == 55);
920 try expect(vec[2] == 99);
921}
922
923test "comptime struct field" {
924 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
925 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO
926
927 const T = struct {
928 a: i32,
929 comptime b: i32 = 1234,
930 };
931
932 comptime std.debug.assert(@sizeOf(T) == 4);
933
934 var foo: T = undefined;
935 _ = &foo;
936 comptime assert(foo.b == 1234);
937}
938
939test "tuple element initialized with fn call" {
940 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
941 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
942 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
943
944 const S = struct {
945 fn doTheTest() !void {
946 const x = .{foo()};
947 try expectEqualSlices(u8, x[0], "hi");
948 }
949 fn foo() []const u8 {
950 return "hi";
951 }
952 };
953 try S.doTheTest();
954 try comptime S.doTheTest();
955}
956
957test "struct with union field" {
958 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
959 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
960 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
961
962 const Value = struct {
963 ref: u32 = 2,
964 kind: union(enum) {
965 None: usize,
966 Bool: bool,
967 },
968 };
969
970 var True = Value{
971 .kind = .{ .Bool = true },
972 };
973 _ = &True;
974 try expect(@as(u32, 2) == True.ref);
975 try expect(True.kind.Bool);
976}
977
978test "struct with 0-length union array field" {
979 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
980 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
981
982 const U = union {
983 a: u32,
984 b: u64,
985 };
986
987 const S = struct {
988 zero_length: [0]U,
989 };
990
991 var s: S = undefined;
992 _ = &s;
993 try expectEqual(@as(usize, 0), s.zero_length.len);
994}
995
996test "packed struct with undefined initializers" {
997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
999 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1000
1001 const S = struct {
1002 const P = packed struct {
1003 a: u3,
1004 _a: u3 = undefined,
1005 b: u3,
1006 _b: u3 = undefined,
1007 c: u3,
1008 _c: u3 = undefined,
1009 };
1010
1011 fn doTheTest() !void {
1012 var p: P = undefined;
1013 p = P{ .a = 2, .b = 4, .c = 6 };
1014 // Make sure the compiler doesn't touch the unprefixed fields.
1015 // Use expect since x86-linux doesn't like expectEqual
1016 try expect(p.a == 2);
1017 try expect(p.b == 4);
1018 try expect(p.c == 6);
1019 }
1020 };
1021
1022 try S.doTheTest();
1023 try comptime S.doTheTest();
1024}
1025
1026test "for loop over pointers to struct, getting field from struct pointer" {
1027 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1028 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1029 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1030
1031 const S = struct {
1032 const Foo = struct {
1033 name: []const u8,
1034 };
1035
1036 var ok = true;
1037
1038 fn eql(a: []const u8) bool {
1039 _ = a;
1040 return true;
1041 }
1042
1043 const ArrayList = struct {
1044 fn toSlice(self: *ArrayList) []*Foo {
1045 _ = self;
1046 return @as([*]*Foo, undefined)[0..0];
1047 }
1048 };
1049
1050 fn doTheTest() !void {
1051 var objects: ArrayList = undefined;
1052
1053 for (objects.toSlice()) |obj| {
1054 if (eql(obj.name)) {
1055 ok = false;
1056 }
1057 }
1058
1059 try expect(ok);
1060 }
1061 };
1062 try S.doTheTest();
1063}
1064
1065test "anon init through error unions and optionals" {
1066 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1067 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1068 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1069 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1070
1071 const S = struct {
1072 a: u32,
1073
1074 fn foo() anyerror!?anyerror!@This() {
1075 return .{ .a = 1 };
1076 }
1077 fn bar() ?anyerror![2]u8 {
1078 return .{ 1, 2 };
1079 }
1080
1081 fn doTheTest() !void {
1082 const a = try (try foo()).?;
1083 const b = try bar().?;
1084 try expect(a.a + b[1] == 3);
1085 }
1086 };
1087
1088 try S.doTheTest();
1089 try comptime S.doTheTest();
1090}
1091
1092test "anon init through optional" {
1093 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1094 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1095 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1096
1097 const S = struct {
1098 a: u32,
1099
1100 fn doTheTest() !void {
1101 var s: ?@This() = null;
1102 s = .{ .a = 1 };
1103 try expect(s.?.a == 1);
1104 }
1105 };
1106
1107 try S.doTheTest();
1108 try comptime S.doTheTest();
1109}
1110
1111test "anon init through error union" {
1112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1113 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1114 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1115
1116 const S = struct {
1117 a: u32,
1118
1119 fn doTheTest() !void {
1120 var s: anyerror!@This() = error.Foo;
1121 s = .{ .a = 1 };
1122 try expect((try s).a == 1);
1123 }
1124 };
1125
1126 try S.doTheTest();
1127 try comptime S.doTheTest();
1128}
1129
1130test "typed init through error unions and optionals" {
1131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1133 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1134
1135 const S = struct {
1136 a: u32,
1137
1138 fn foo() anyerror!?anyerror!@This() {
1139 return @This(){ .a = 1 };
1140 }
1141 fn bar() ?anyerror![2]u8 {
1142 return [2]u8{ 1, 2 };
1143 }
1144
1145 fn doTheTest() !void {
1146 const a = try (try foo()).?;
1147 const b = try bar().?;
1148 try expect(a.a + b[1] == 3);
1149 }
1150 };
1151
1152 try S.doTheTest();
1153 try comptime S.doTheTest();
1154}
1155
1156test "initialize struct with empty literal" {
1157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1158
1159 const S = struct { x: i32 = 1234 };
1160 var s: S = .{};
1161 _ = &s;
1162 try expect(s.x == 1234);
1163}
1164
1165test "loading a struct pointer perfoms a copy" {
1166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1167
1168 const S = struct {
1169 a: i32,
1170 b: i32,
1171 c: i32,
1172
1173 fn swap(a: *@This(), b: *@This()) void {
1174 const tmp = a.*;
1175 a.* = b.*;
1176 b.* = tmp;
1177 }
1178 };
1179 var s1: S = .{ .a = 1, .b = 2, .c = 3 };
1180 var s2: S = .{ .a = 4, .b = 5, .c = 6 };
1181 S.swap(&s1, &s2);
1182 try expect(s1.a == 4);
1183 try expect(s1.b == 5);
1184 try expect(s1.c == 6);
1185 try expect(s2.a == 1);
1186 try expect(s2.b == 2);
1187 try expect(s2.c == 3);
1188}
1189
1190test "packed struct aggregate init" {
1191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1195
1196 const S = struct {
1197 fn foo(a: i2, b: i6) u8 {
1198 return @as(u8, @bitCast(P{ .a = a, .b = b }));
1199 }
1200
1201 const P = packed struct {
1202 a: i2,
1203 b: i6,
1204 };
1205 };
1206 const result = @as(u8, @bitCast(S.foo(1, 2)));
1207 try expect(result == 9);
1208}
1209
1210test "packed struct field access via pointer" {
1211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1212 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1213 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1214 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1215
1216 const S = struct {
1217 fn doTheTest() !void {
1218 const S = packed struct { a: u30 };
1219 var s1: S = .{ .a = 1 };
1220 const s2 = &s1;
1221 try expect(s2.a == 1);
1222 var s3: S = undefined;
1223 const s4 = &s3;
1224 _ = s4;
1225 }
1226 };
1227 try S.doTheTest();
1228 try comptime S.doTheTest();
1229}
1230
1231test "store to comptime field" {
1232 {
1233 const S = struct {
1234 comptime a: [2]u32 = [2]u32{ 1, 2 },
1235 };
1236 var s: S = .{};
1237 s.a = [2]u32{ 1, 2 };
1238 s.a[0] = 1;
1239 }
1240 {
1241 const T = struct { a: u32, b: u32 };
1242 const S = struct {
1243 comptime a: T = T{ .a = 1, .b = 2 },
1244 };
1245 var s: S = .{};
1246 s.a = T{ .a = 1, .b = 2 };
1247 s.a.a = 1;
1248 }
1249}
1250
1251test "struct field init value is size of the struct" {
1252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1253
1254 const namespace = struct {
1255 const S = extern struct {
1256 size: u8 = @sizeOf(S),
1257 blah: u16,
1258 };
1259 };
1260 var s: namespace.S = .{ .blah = 1234 };
1261 _ = &s;
1262 try expect(s.size == 4);
1263}
1264
1265test "under-aligned struct field" {
1266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1267 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1268 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1269 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1270
1271 const U = extern union {
1272 fd: i32,
1273 u32: u32,
1274 u64: u64,
1275 };
1276 const S = extern struct {
1277 events: u32,
1278 data: U align(4),
1279 };
1280 var runtime: usize = 1234;
1281 _ = &runtime;
1282 const ptr = &S{ .events = 0, .data = .{ .u64 = runtime } };
1283 const array = @as(*const [12]u8, @ptrCast(ptr));
1284 const result = std.mem.readInt(u64, array[4..12], native_endian);
1285 try expect(result == 1234);
1286}
1287
1288test "fieldParentPtr of a zero-bit field" {
1289 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1290 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1291 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1292
1293 const S = struct {
1294 fn testStruct(comptime A: type) !void {
1295 {
1296 const a = A{ .u = 0 };
1297 const b_ptr = &a.b;
1298 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1299 try std.testing.expectEqual(&a, a_ptr);
1300 }
1301 {
1302 var a = A{ .u = 0 };
1303 const b_ptr = &a.b;
1304 const a_ptr: *A = @fieldParentPtr("b", b_ptr);
1305 try std.testing.expectEqual(&a, a_ptr);
1306 }
1307 }
1308 fn testNestedStruct(comptime A: type) !void {
1309 {
1310 const a = A{ .u = 0 };
1311 const c_ptr = &a.b.c;
1312 const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr);
1313 try std.testing.expectEqual(&a.b, b_ptr);
1314 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1315 try std.testing.expectEqual(&a, a_ptr);
1316 }
1317 {
1318 var a = A{ .u = 0 };
1319 const c_ptr = &a.b.c;
1320 const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr);
1321 try std.testing.expectEqual(&a.b, b_ptr);
1322 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1323 try std.testing.expectEqual(&a, a_ptr);
1324 }
1325 }
1326 fn doTheTest() !void {
1327 try testStruct(struct { b: void = {}, u: u8 });
1328 try testStruct(struct { u: u8, b: void = {} });
1329 try testNestedStruct(struct { b: struct { c: void = {} } = .{}, u: u8 });
1330 try testNestedStruct(struct { u: u8, b: struct { c: void = {} } = .{} });
1331 }
1332 };
1333 try S.doTheTest();
1334 try comptime S.doTheTest();
1335}
1336
1337test "struct field has a pointer to an aligned version of itself" {
1338 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1339
1340 const E = struct {
1341 next: *align(1) @This(),
1342 };
1343 var e: E = undefined;
1344 e = .{ .next = &e };
1345
1346 try expect(&e == e.next);
1347}
1348
1349test "struct has only one reference" {
1350 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1351
1352 const S = struct {
1353 fn optionalStructParam(_: ?struct { x: u8 }) void {}
1354 fn errorUnionStructParam(_: error{}!struct { x: u8 }) void {}
1355 fn optionalStructReturn() ?struct { x: u8 } {
1356 return null;
1357 }
1358 fn errorUnionStructReturn() error{Foo}!struct { x: u8 } {
1359 return error.Foo;
1360 }
1361
1362 fn pointerPackedStruct(_: *packed struct { x: u8 }) void {}
1363 fn nestedPointerPackedStruct(_: struct { x: *packed struct { x: u8 } }) void {}
1364 fn pointerNestedPackedStruct(_: *struct { x: packed struct { x: u8 } }) void {}
1365 fn pointerNestedPointerPackedStruct(_: *struct { x: *packed struct { x: u8 } }) void {}
1366
1367 fn optionalComptimeIntParam(comptime x: ?comptime_int) comptime_int {
1368 return x.?;
1369 }
1370 fn errorUnionComptimeIntParam(comptime x: error{}!comptime_int) comptime_int {
1371 return x catch unreachable;
1372 }
1373 };
1374
1375 const optional_struct_param: *const anyopaque = &S.optionalStructParam;
1376 const error_union_struct_param: *const anyopaque = &S.errorUnionStructParam;
1377 try expect(optional_struct_param != error_union_struct_param);
1378
1379 const optional_struct_return: *const anyopaque = &S.optionalStructReturn;
1380 const error_union_struct_return: *const anyopaque = &S.errorUnionStructReturn;
1381 try expect(optional_struct_return != error_union_struct_return);
1382
1383 const pointer_packed_struct: *const anyopaque = &S.pointerPackedStruct;
1384 const nested_pointer_packed_struct: *const anyopaque = &S.nestedPointerPackedStruct;
1385 try expect(pointer_packed_struct != nested_pointer_packed_struct);
1386
1387 const pointer_nested_packed_struct: *const anyopaque = &S.pointerNestedPackedStruct;
1388 const pointer_nested_pointer_packed_struct: *const anyopaque = &S.pointerNestedPointerPackedStruct;
1389 try expect(pointer_nested_packed_struct != pointer_nested_pointer_packed_struct);
1390
1391 try expectEqual(@alignOf(struct {}), S.optionalComptimeIntParam(@alignOf(struct {})));
1392 try expectEqual(@alignOf(struct { x: u8 }), S.errorUnionComptimeIntParam(@alignOf(struct { x: u8 })));
1393 try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 })));
1394 try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 })));
1395}
1396
1397test "no dependency loop on pointer to optional struct" {
1398 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1399 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1400
1401 const S = struct {
1402 const A = struct { b: B };
1403 const B = struct { a: *?A };
1404 };
1405 var a1: ?S.A = null;
1406 var a2: ?S.A = .{ .b = .{ .a = &a1 } };
1407 a1 = .{ .b = .{ .a = &a2 } };
1408
1409 try expect(a1.?.b.a == &a2);
1410 try expect(a2.?.b.a == &a1);
1411}
1412
1413test "discarded struct initialization works as expected" {
1414 const S = struct { a: u32 };
1415 _ = S{ .a = 1 };
1416}
1417
1418test "function pointer in struct returns the struct" {
1419 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1420
1421 const A = struct {
1422 const A = @This();
1423 ptr: *const fn () A,
1424
1425 fn f() A {
1426 return .{ .ptr = f };
1427 }
1428 };
1429 var a = A.f();
1430 _ = &a;
1431 try expect(a.ptr == A.f);
1432}
1433
1434test "no dependency loop on optional field wrapped in generic function" {
1435 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1436
1437 const S = struct {
1438 fn Atomic(comptime T: type) type {
1439 return T;
1440 }
1441 const A = struct { b: Atomic(?*B) };
1442 const B = struct { a: ?*A };
1443 };
1444 var a: S.A = .{ .b = null };
1445 var b: S.B = .{ .a = &a };
1446 a.b = &b;
1447
1448 try expect(a.b == &b);
1449 try expect(b.a == &a);
1450}
1451
1452test "optional field init with tuple" {
1453 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1454
1455 const S = struct {
1456 a: ?struct { b: u32 },
1457 };
1458 var a: u32 = 0;
1459 _ = &a;
1460 const b = S{
1461 .a = .{ .b = a },
1462 };
1463 try expect(b.a.?.b == a);
1464}
1465
1466test "if inside struct init inside if" {
1467 const MyStruct = struct { x: u32 };
1468 const b: u32 = 5;
1469 var i: u32 = 1;
1470 _ = &i;
1471 const my_var = if (i < 5)
1472 MyStruct{
1473 .x = 1 + if (i > 0) b else 0,
1474 }
1475 else
1476 MyStruct{
1477 .x = 1 + if (i > 0) b else 0,
1478 };
1479 try expect(my_var.x == 6);
1480}
1481
1482test "optional generic function label struct field" {
1483 const Options = struct {
1484 isFoo: ?fn (comptime type) u8 = defaultIsFoo,
1485 fn defaultIsFoo(comptime _: type) u8 {
1486 return 123;
1487 }
1488 };
1489 try expect((Options{}).isFoo.?(u8) == 123);
1490}
1491
1492test "struct fields get automatically reordered" {
1493 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1494 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1495 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1496
1497 const S1 = struct {
1498 a: u32,
1499 b: u32,
1500 c: bool,
1501 d: bool,
1502 };
1503 const S2 = struct {
1504 a: u32,
1505 b: bool,
1506 c: u32,
1507 d: bool,
1508 };
1509 try expect(@sizeOf(S1) == @sizeOf(S2));
1510}
1511
1512test "directly initiating tuple like struct" {
1513 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1514
1515 const a = struct { u8 }{8};
1516 try expect(a[0] == 8);
1517}
1518
1519test "instantiate struct with comptime field" {
1520 {
1521 var things = struct {
1522 comptime foo: i8 = 1,
1523 }{};
1524 _ = &things;
1525 comptime std.debug.assert(things.foo == 1);
1526 }
1527
1528 {
1529 const T = struct {
1530 comptime foo: i8 = 1,
1531 };
1532 var things = T{};
1533 _ = &things;
1534 comptime std.debug.assert(things.foo == 1);
1535 }
1536
1537 {
1538 var things: struct {
1539 comptime foo: i8 = 1,
1540 } = .{};
1541 _ = &things;
1542 comptime std.debug.assert(things.foo == 1);
1543 }
1544
1545 {
1546 var things: struct {
1547 comptime foo: i8 = 1,
1548 } = undefined; // Segmentation fault at address 0x0
1549 _ = &things;
1550 comptime std.debug.assert(things.foo == 1);
1551 }
1552}
1553
1554test "struct field pointer has correct alignment" {
1555 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1556 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1557 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1558 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1559
1560 const S = struct {
1561 fn doTheTest() !void {
1562 var a: struct { x: u32 } = .{ .x = 123 };
1563 var b: struct { x: u32 } align(1) = .{ .x = 456 };
1564 var c: struct { x: u32 } align(64) = .{ .x = 789 };
1565
1566 const ap = &a.x;
1567 const bp = &b.x;
1568 const cp = &c.x;
1569
1570 comptime assert(@TypeOf(ap) == *u32);
1571 comptime assert(@TypeOf(bp) == *align(1) u32);
1572 comptime assert(@TypeOf(cp) == *u32); // undefined layout, cannot inherit larger alignment
1573
1574 try expectEqual(@as(u32, 123), ap.*);
1575 try expectEqual(@as(u32, 456), bp.*);
1576 try expectEqual(@as(u32, 789), cp.*);
1577 }
1578 };
1579
1580 try S.doTheTest();
1581 try comptime S.doTheTest();
1582}
1583
1584test "extern struct field pointer has correct alignment" {
1585 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1586 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1587 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1588 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1589
1590 const S = struct {
1591 fn doTheTest() !void {
1592 var a: extern struct { x: u32, y: u16 } = .{ .x = 1, .y = 2 };
1593 var b: extern struct { x: u32, y: u16 } align(1) = .{ .x = 3, .y = 4 };
1594 var c: extern struct { x: u32, y: u16 } align(64) = .{ .x = 5, .y = 6 };
1595
1596 const axp = &a.x;
1597 const bxp = &b.x;
1598 const cxp = &c.x;
1599 const ayp = &a.y;
1600 const byp = &b.y;
1601 const cyp = &c.y;
1602
1603 comptime assert(@TypeOf(axp) == *u32);
1604 comptime assert(@TypeOf(bxp) == *align(1) u32);
1605 comptime assert(@TypeOf(cxp) == *align(64) u32);
1606
1607 comptime assert(@TypeOf(ayp) == *align(@alignOf(u32)) u16);
1608 comptime assert(@TypeOf(byp) == *align(1) u16);
1609 comptime assert(@TypeOf(cyp) == *align(@alignOf(u32)) u16);
1610
1611 try expectEqual(@as(u32, 1), axp.*);
1612 try expectEqual(@as(u32, 3), bxp.*);
1613 try expectEqual(@as(u32, 5), cxp.*);
1614
1615 try expectEqual(@as(u16, 2), ayp.*);
1616 try expectEqual(@as(u16, 4), byp.*);
1617 try expectEqual(@as(u16, 6), cyp.*);
1618 }
1619 };
1620
1621 try S.doTheTest();
1622 try comptime S.doTheTest();
1623}
1624
1625test "packed struct field in anonymous struct" {
1626 const T = packed struct {
1627 f1: bool = false,
1628 };
1629
1630 try std.testing.expect(countFields(.{ .t = T{} }) == 1);
1631}
1632fn countFields(v: anytype) usize {
1633 return @typeInfo(@TypeOf(v)).@"struct".fields.len;
1634}
1635
1636test "struct init with no result pointer sets field result types" {
1637 const S = struct {
1638 // A function parameter has a result type, but no result pointer.
1639 fn f(s: struct { x: u32 }) u32 {
1640 return s.x;
1641 }
1642 };
1643
1644 const x: u64 = 123;
1645 const y = S.f(.{ .x = @intCast(x) });
1646
1647 try expect(y == x);
1648}
1649
1650test "runtime side-effects in comptime-known struct init" {
1651 var side_effects: u4 = 0;
1652 const S = struct { a: u4, b: u4, c: u4, d: u4 };
1653 const init = S{
1654 .d = blk: {
1655 side_effects += 8;
1656 break :blk 8;
1657 },
1658 .c = blk: {
1659 side_effects += 4;
1660 break :blk 4;
1661 },
1662 .b = blk: {
1663 side_effects += 2;
1664 break :blk 2;
1665 },
1666 .a = blk: {
1667 side_effects += 1;
1668 break :blk 1;
1669 },
1670 };
1671 try expectEqual(S{ .a = 1, .b = 2, .c = 4, .d = 8 }, init);
1672 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
1673}
1674
1675test "pointer to struct initialized through reference to anonymous initializer provides result types" {
1676 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1677
1678 const S = struct { a: u8, b: u16, c: *const anyopaque };
1679 var my_u16: u16 = 0xABCD;
1680 _ = &my_u16;
1681 const s: *const S = &.{
1682 // intentionally out of order
1683 .c = @ptrCast("hello"),
1684 .b = my_u16,
1685 .a = @truncate(my_u16),
1686 };
1687 try expect(s.a == 0xCD);
1688 try expect(s.b == 0xABCD);
1689 const str: *const [5]u8 = @ptrCast(s.c);
1690 try std.testing.expectEqualSlices(u8, "hello", str);
1691}
1692
1693test "comptimeness of optional and error union payload is analyzed properly" {
1694 // This is primarily a semantic analysis integrity test.
1695 // The original failure mode for this was a crash.
1696 // Both structs and unions work for this, the point is that
1697 // their comptimeness is lazily evaluated.
1698 const S = struct {};
1699 // Original form of bug #17511, regressed in #17471
1700 const a = @sizeOf(?*S);
1701 _ = a;
1702 // Error union case, fails assertion in debug versions of release 0.11.0
1703 _ = @sizeOf(anyerror!*S);
1704 _ = @sizeOf(anyerror!?S);
1705 // Evaluation case, crashes the actual release 0.11.0
1706 const C = struct { x: comptime_int };
1707 const c: anyerror!?C = .{ .x = 3 };
1708 const x = (try c).?.x;
1709 try std.testing.expectEqual(3, x);
1710}
1711
1712test "initializer uses own alignment" {
1713 const S = struct {
1714 x: u32 = @alignOf(@This()) + 1,
1715 };
1716
1717 var s: S = .{};
1718 _ = &s;
1719 try expectEqual(4, @alignOf(S));
1720 try expectEqual(@as(usize, 5), s.x);
1721}
1722
1723test "initializer uses own size" {
1724 const S = struct {
1725 x: u32 = @sizeOf(@This()) + 1,
1726 };
1727
1728 var s: S = .{};
1729 _ = &s;
1730 try expectEqual(4, @sizeOf(S));
1731 try expectEqual(@as(usize, 5), s.x);
1732}
1733
1734test "initializer takes a pointer to a variable inside its struct" {
1735 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1736
1737 const namespace = struct {
1738 const S = struct {
1739 s: *S = &S.instance,
1740 var instance: S = undefined;
1741 };
1742
1743 fn doTheTest() !void {
1744 var foo: S = .{};
1745 _ = &foo;
1746 try expectEqual(&S.instance, foo.s);
1747 }
1748 };
1749
1750 try namespace.doTheTest();
1751 comptime try namespace.doTheTest();
1752}
1753
1754test "circular dependency through pointer field of a struct" {
1755 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1756
1757 const S = struct {
1758 const StructInner = extern struct {
1759 outer: StructOuter = std.mem.zeroes(StructOuter),
1760 };
1761
1762 const StructMiddle = extern struct {
1763 outer: ?*StructInner,
1764 inner: ?*StructOuter,
1765 };
1766
1767 const StructOuter = extern struct {
1768 middle: StructMiddle = std.mem.zeroes(StructMiddle),
1769 };
1770 };
1771 var outer: S.StructOuter = .{};
1772 _ = &outer;
1773 try expect(outer.middle.outer == null);
1774 try expect(outer.middle.inner == null);
1775}
1776
1777test "field calls do not force struct field init resolution" {
1778 const S = struct {
1779 x: u32 = blk: {
1780 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution
1781 break :blk 123;
1782 },
1783 dummyFn: *const fn () void = undefined,
1784 fn make() @This() {
1785 return .{};
1786 }
1787 };
1788 var s: S = .{};
1789 _ = &s;
1790 try expect(s.x == 123);
1791}
1792
1793test "tuple with comptime-only field" {
1794 const S = struct {
1795 fn getTuple() struct { comptime_int } {
1796 return struct { comptime comptime_int = 0 }{0};
1797 }
1798 };
1799
1800 const x = S.getTuple();
1801 try expect(x.@"0" == 0);
1802}
1803
1804test "extern struct fields are aligned to 1" {
1805 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1806
1807 const Foo = extern struct {
1808 a: u8 align(1),
1809 b: u16 align(1),
1810 };
1811
1812 const foo = Foo{
1813 .a = 1,
1814 .b = 2,
1815 };
1816 try std.testing.expectEqual(1, foo.a);
1817 try std.testing.expectEqual(2, foo.b);
1818}
1819
1820test "assign to slice.len of global variable" {
1821 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1822 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1823 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1824 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1825 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1826
1827 const S = struct {
1828 const allocator = std.testing.allocator;
1829 var list = std.array_list.Managed(u32).init(allocator);
1830 };
1831
1832 S.list.items.len = 0;
1833 try expect(S.list.items.len == 0);
1834}
1835
1836test "pointers to fields of volatile pointer to struct are also volatile" {
1837 const B = extern struct {
1838 a: u32,
1839 b: i32,
1840 };
1841 const A = extern struct {
1842 value: *volatile B,
1843 };
1844
1845 var a: *A = undefined;
1846 try expect(@TypeOf(&a.value.a) == *volatile u32);
1847 try expect(@TypeOf(&a.value.b) == *volatile i32);
1848}
1849
1850test "pointers to fields of volatile pointer to union are also volatile" {
1851 const D = extern union {
1852 a: u32,
1853 b: i32,
1854 };
1855 const C = extern struct {
1856 value: *volatile D,
1857 };
1858
1859 var c: *C = undefined;
1860 try expect(@TypeOf(&c.value.a) == *volatile u32);
1861 try expect(@TypeOf(&c.value.b) == *volatile i32);
1862}
1863
1864test "array of structs inside struct initialized with undefined" {
1865 const Item = struct { field: u8 };
1866 const Thing = struct {
1867 array: [1]Item,
1868 };
1869 _ = Thing{ .array = undefined };
1870}
1871
1872test "runtime call in nested initializer" {
1873 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1874 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1875
1876 const Holder = struct {
1877 array: []const u8,
1878 };
1879 const Test = struct {
1880 holders: []const Holder,
1881 };
1882 const Letter = enum(u8) {
1883 A = 0x41,
1884 B,
1885
1886 fn letter(e: @This()) u8 {
1887 return @intFromEnum(e);
1888 }
1889 };
1890
1891 const test_struct = Test{
1892 .holders = &.{
1893 Holder{
1894 .array = &.{
1895 Letter.letter(.A),
1896 },
1897 },
1898 },
1899 };
1900 try std.testing.expectEqualStrings("A", test_struct.holders[0].array);
1901}
1902
1903test "runtime value in nested initializer passed as pointer to function" {
1904 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1905
1906 const Bar = struct {
1907 b: u32,
1908 };
1909 const Foo = struct {
1910 a: Bar,
1911
1912 fn takeFoo(foo: *const @This()) !void {
1913 try std.testing.expectEqual(@as(u32, 24), foo.a.b);
1914 }
1915 };
1916
1917 var baz: u32 = 24;
1918 _ = &baz;
1919 try Foo.takeFoo(&.{
1920 .a = .{
1921 .b = baz,
1922 },
1923 });
1924}
1925
1926test "struct field default value is a call" {
1927 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1928 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1929
1930 const Z = packed struct {
1931 a: u32,
1932 };
1933 const Y = struct {
1934 a: u16,
1935 b: bool,
1936 c: Z,
1937 d: Z,
1938
1939 fn init() @This() {
1940 return .{
1941 .a = 0,
1942 .b = false,
1943 .c = @as(Z, @bitCast(@as(u32, 0))),
1944 .d = @as(Z, @bitCast(@as(u32, 0))),
1945 };
1946 }
1947 };
1948 const X = struct {
1949 y: Y = Y.init(),
1950 };
1951
1952 const x = X{};
1953 try std.testing.expectEqual(@as(u16, 0), x.y.a);
1954 try std.testing.expectEqual(false, x.y.b);
1955 try std.testing.expectEqual(Z{ .a = 0 }, x.y.c);
1956 try std.testing.expectEqual(Z{ .a = 0 }, x.y.d);
1957}
1958
1959test "aggregate initializers should allow initializing comptime fields, verifying equality" {
1960 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1961
1962 var x: u32 = 15;
1963 _ = &x;
1964 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
1965 const a: T = .{ -1234, 5678, x + 1 };
1966
1967 try expect(a[0] == -1234);
1968 try expect(a[1] == 5678);
1969 try expect(a[2] == 16);
1970}
1971
1972test "assignment of field with padding" {
1973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1974 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1975
1976 const Mesh = extern struct {
1977 id: u32,
1978 };
1979 const Material = extern struct {
1980 transparent: bool = true,
1981 emits_shadows: bool = true,
1982 render_color: bool = true,
1983 };
1984 const Renderable = extern struct {
1985 material: Material,
1986 mesh: Mesh,
1987 };
1988 var renderable: Renderable = undefined;
1989 renderable = Renderable{
1990 .mesh = Mesh{ .id = 0 },
1991 .material = Material{
1992 .transparent = false,
1993 .emits_shadows = false,
1994 },
1995 };
1996 try expect(false == renderable.material.transparent);
1997 try expect(false == renderable.material.emits_shadows);
1998 try expect(true == renderable.material.render_color);
1999}
2000
2001test "initiate global variable with runtime value" {
2002 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2003 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2004
2005 const S = struct {
2006 field: i32,
2007 fn couldFail() anyerror!i32 {
2008 return 1;
2009 }
2010 var some_struct: @This() = undefined;
2011 };
2012
2013 S.some_struct = .{
2014 .field = S.couldFail() catch 0,
2015 };
2016 try expect(S.some_struct.field == 1);
2017}
2018
2019test "struct containing optional pointer to array of @This()" {
2020 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2021 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2022
2023 const S = struct {
2024 x: ?*const [1]@This(),
2025 };
2026
2027 var s: S = .{ .x = &.{.{ .x = null }} };
2028 _ = &s;
2029 try expect(s.x.?[0].x == null);
2030}
2031
2032test "matching captures causes struct equivalence" {
2033 const S = struct {
2034 fn UnsignedWrapper(comptime I: type) type {
2035 const bits = @typeInfo(I).int.bits;
2036 return struct {
2037 x: @Int(.unsigned, bits),
2038 };
2039 }
2040 };
2041
2042 comptime assert(S.UnsignedWrapper(u8) == S.UnsignedWrapper(i8));
2043 comptime assert(S.UnsignedWrapper(u16) == S.UnsignedWrapper(i16));
2044 comptime assert(S.UnsignedWrapper(u8) != S.UnsignedWrapper(u16));
2045
2046 const a: S.UnsignedWrapper(u8) = .{ .x = 10 };
2047 const b: S.UnsignedWrapper(i8) = .{ .x = 10 };
2048 comptime assert(@TypeOf(a) == @TypeOf(b));
2049 try expect(a.x == b.x);
2050}
2051
2052test "struct @FieldType" {
2053 const S = struct {
2054 a: u32,
2055 b: f64,
2056 c: *@This(),
2057 };
2058
2059 comptime assert(@FieldType(S, "a") == u32);
2060 comptime assert(@FieldType(S, "b") == f64);
2061 comptime assert(@FieldType(S, "c") == *S);
2062}
2063
2064test "extern struct @FieldType" {
2065 const S = extern struct {
2066 a: u32,
2067 b: f64,
2068 c: *@This(),
2069 };
2070
2071 comptime assert(@FieldType(S, "a") == u32);
2072 comptime assert(@FieldType(S, "b") == f64);
2073 comptime assert(@FieldType(S, "c") == *S);
2074}
2075
2076test "anonymous struct equivalence" {
2077 const S = struct {
2078 fn anonStructType(comptime x: anytype) type {
2079 const val = .{ .a = "hello", .b = x };
2080 return @TypeOf(val);
2081 }
2082 };
2083
2084 const A = S.anonStructType(123);
2085 const B = S.anonStructType(123);
2086 const C = S.anonStructType(456);
2087
2088 comptime assert(A == B);
2089 comptime assert(A != C);
2090 comptime assert(B != C);
2091}
2092
2093test "field access through mem ptr arg" {
2094 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2095 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2096
2097 const S = struct {
2098 fn nestedFieldAccess(
2099 _: usize,
2100 _: usize,
2101 _: usize,
2102 _: usize,
2103 _: usize,
2104 _: usize,
2105 _: usize,
2106 _: usize,
2107 ptr_struct: *const struct { field: u32 },
2108 ) u32 {
2109 return ptr_struct.field;
2110 }
2111 };
2112 try expect(S.nestedFieldAccess(
2113 undefined,
2114 undefined,
2115 undefined,
2116 undefined,
2117 undefined,
2118 undefined,
2119 undefined,
2120 undefined,
2121 &.{ .field = 0x6b00a2eb },
2122 ) == 0x6b00a2eb);
2123 comptime assert(S.nestedFieldAccess(
2124 undefined,
2125 undefined,
2126 undefined,
2127 undefined,
2128 undefined,
2129 undefined,
2130 undefined,
2131 undefined,
2132 &.{ .field = 0x0ced271f },
2133 ) == 0x0ced271f);
2134}
2135
2136test "align 1 struct parameter dereferenced and returned" {
2137 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2138
2139 const S = extern struct {
2140 a: u32,
2141
2142 fn gimme(p: *align(1) @This()) @This() {
2143 return p.*;
2144 }
2145 };
2146 var buffer: [5]u8 align(4) = .{ 1, 2, 3, 4, 5 };
2147 const s = S.gimme(@ptrCast(buffer[1..]));
2148 switch (native_endian) {
2149 .big => try expect(s.a == 0x02030405),
2150 .little => try expect(s.a == 0x05040302),
2151 }
2152}
2153
2154test "avoid unused field function body compile error" {
2155 const Case = struct {
2156 const This = @This();
2157
2158 const S = struct {
2159 a: usize = 1,
2160 b: fn () void = This.functionThatDoesNotCompile,
2161 };
2162
2163 const s: S = .{};
2164
2165 fn entry() usize {
2166 return s.a;
2167 }
2168
2169 pub fn functionThatDoesNotCompile() void {
2170 @compileError("told you so");
2171 }
2172 };
2173
2174 try expect(Case.entry() == 1);
2175}