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 = {},
299 .b = 1,
300 .c = {},
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_aarch64) return error.SkipZigTest;
382
383 var foo = APackedStruct{
384 .x = 1,
385 .y = 2,
386 };
387 foo.y += 1;
388 const four = foo.x + foo.y;
389 try expect(four == 4);
390}
391
392const Foo24Bits = packed struct {
393 field: u24,
394};
395const Foo96Bits = packed struct {
396 a: u24,
397 b: u24,
398 c: u24,
399 d: u24,
400};
401
402test "packed struct 24bits" {
403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
404 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
407 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
408
409 comptime {
410 std.debug.assert(@sizeOf(Foo24Bits) == @sizeOf(u24));
411 std.debug.assert(@sizeOf(Foo96Bits) == @sizeOf(u96));
412 }
413
414 var value = Foo96Bits{
415 .a = 0,
416 .b = 0,
417 .c = 0,
418 .d = 0,
419 };
420 value.a += 1;
421 try expect(value.a == 1);
422 try expect(value.b == 0);
423 try expect(value.c == 0);
424 try expect(value.d == 0);
425
426 value.b += 1;
427 try expect(value.a == 1);
428 try expect(value.b == 1);
429 try expect(value.c == 0);
430 try expect(value.d == 0);
431
432 value.c += 1;
433 try expect(value.a == 1);
434 try expect(value.b == 1);
435 try expect(value.c == 1);
436 try expect(value.d == 0);
437
438 value.d += 1;
439 try expect(value.a == 1);
440 try expect(value.b == 1);
441 try expect(value.c == 1);
442 try expect(value.d == 1);
443}
444
445test "runtime struct initialization of bitfield" {
446 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
447 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
450
451 const s1 = Nibbles{
452 .x = x1,
453 .y = x1,
454 };
455 const s2 = Nibbles{
456 .x = @as(u4, @intCast(x2)),
457 .y = @as(u4, @intCast(x2)),
458 };
459
460 try expect(s1.x == x1);
461 try expect(s1.y == x1);
462 try expect(s2.x == @as(u4, @intCast(x2)));
463 try expect(s2.y == @as(u4, @intCast(x2)));
464}
465
466var x1 = @as(u4, 1);
467var x2 = @as(u8, 2);
468
469const Nibbles = packed struct {
470 x: u4,
471 y: u4,
472};
473
474const Bitfields = packed struct {
475 f1: u16,
476 f2: u16,
477 f3: u8,
478 f4: u8,
479 f5: u4,
480 f6: u4,
481 f7: u8,
482};
483
484test "packed struct fields are ordered from LSB to MSB" {
485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
489 var all: u64 = 0x7765443322221111;
490 var bytes: [8]u8 align(@alignOf(Bitfields)) = undefined;
491 @memcpy(bytes[0..8], @as([*]u8, @ptrCast(&all)));
492 const bitfields = @as(*Bitfields, @ptrCast(&bytes)).*;
493
494 try expect(bitfields.f1 == 0x1111);
495 try expect(bitfields.f2 == 0x2222);
496 try expect(bitfields.f3 == 0x33);
497 try expect(bitfields.f4 == 0x44);
498 try expect(bitfields.f5 == 0x5);
499 try expect(bitfields.f6 == 0x6);
500 try expect(bitfields.f7 == 0x77);
501}
502
503test "implicit cast packed struct field to const ptr" {
504 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
505 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
508
509 const LevelUpMove = packed struct {
510 move_id: u9,
511 level: u7,
512
513 fn toInt(value: u7) u7 {
514 return value;
515 }
516 };
517
518 var lup: LevelUpMove = undefined;
519 lup.level = 12;
520 const res = LevelUpMove.toInt(lup.level);
521 try expect(res == 12);
522}
523
524test "zero-bit field in packed struct" {
525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
526
527 const S = packed struct {
528 x: u10,
529 y: void,
530 };
531 var x: S = undefined;
532 _ = &x;
533}
534
535test "packed struct with non-ABI-aligned field" {
536 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
539 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
541
542 const S = packed struct {
543 x: u9,
544 y: u183,
545 };
546 var s: S = undefined;
547 s.x = 1;
548 s.y = 42;
549 try expect(s.x == 1);
550 try expect(s.y == 42);
551}
552
553const BitField1 = packed struct {
554 a: u3,
555 b: u3,
556 c: u2,
557};
558
559const bit_field_1 = BitField1{
560 .a = 1,
561 .b = 2,
562 .c = 3,
563};
564
565test "bit field access" {
566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
567 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
569 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
570
571 var data = bit_field_1;
572 try expect(getA(&data) == 1);
573 try expect(getB(&data) == 2);
574 try expect(getC(&data) == 3);
575 comptime assert(@sizeOf(BitField1) == 1);
576
577 data.b += 1;
578 try expect(data.b == 3);
579
580 data.a += 1;
581 try expect(data.a == 2);
582 try expect(data.b == 3);
583}
584
585fn getA(data: *const BitField1) u3 {
586 return data.a;
587}
588
589fn getB(data: *const BitField1) u3 {
590 return data.b;
591}
592
593fn getC(data: *const BitField1) u2 {
594 return data.c;
595}
596
597test "default struct initialization fields" {
598 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
599
600 const S = struct {
601 a: i32 = 1234,
602 b: i32,
603 };
604 const x = S{
605 .b = 5,
606 };
607 var five: i32 = 5;
608 _ = &five;
609 const y = S{
610 .b = five,
611 };
612 if (x.a + x.b != 1239) {
613 @compileError("it should be comptime-known");
614 }
615 try expect(y.a == x.a);
616 try expect(y.b == x.b);
617 try expect(1239 == x.a + x.b);
618}
619
620test "packed array 24bits" {
621 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
622 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
623 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
624 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
625
626 comptime {
627 try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
628 try expect(@sizeOf(FooArray24Bits) == @sizeOf(u96));
629 }
630
631 var bytes: [@sizeOf(FooArray24Bits) + 1]u8 = @splat(0);
632 bytes[bytes.len - 1] = 0xbb;
633 const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
634 try expect(ptr.a == 0);
635 try expect(ptr.b0.field == 0);
636 try expect(ptr.b1.field == 0);
637 try expect(ptr.c == 0);
638
639 ptr.a = maxInt(u16);
640 try expect(ptr.a == maxInt(u16));
641 try expect(ptr.b0.field == 0);
642 try expect(ptr.b1.field == 0);
643 try expect(ptr.c == 0);
644
645 ptr.b0.field = maxInt(u24);
646 try expect(ptr.a == maxInt(u16));
647 try expect(ptr.b0.field == maxInt(u24));
648 try expect(ptr.b1.field == 0);
649 try expect(ptr.c == 0);
650
651 ptr.b1.field = maxInt(u24);
652 try expect(ptr.a == maxInt(u16));
653 try expect(ptr.b0.field == maxInt(u24));
654 try expect(ptr.b1.field == maxInt(u24));
655 try expect(ptr.c == 0);
656
657 ptr.c = maxInt(u16);
658 try expect(ptr.a == maxInt(u16));
659 try expect(ptr.b0.field == maxInt(u24));
660 try expect(ptr.b1.field == maxInt(u24));
661 try expect(ptr.c == maxInt(u16));
662
663 try expect(bytes[bytes.len - 1] == 0xbb);
664}
665
666const Foo32Bits = packed struct {
667 field: u24,
668 pad: u8,
669};
670
671const FooArray24Bits = packed struct {
672 a: u16,
673 b0: Foo32Bits,
674 b1: Foo32Bits,
675 c: u16,
676};
677
678const FooStructAligned = packed struct {
679 a: u8,
680 b: u8,
681};
682
683const FooArrayOfAligned = packed struct {
684 a: [2]FooStructAligned,
685};
686
687test "pointer to packed struct member in a stack variable" {
688 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
689 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
690 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
691 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
692
693 const S = packed struct {
694 a: u2,
695 b: u2,
696 };
697
698 var s = S{ .a = 2, .b = 0 };
699 const b_ptr = &s.b;
700 try expect(s.b == 0);
701 b_ptr.* = 2;
702 try expect(s.b == 2);
703}
704
705test "packed struct with u0 field access" {
706 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
707
708 const S = packed struct {
709 f0: u0,
710 };
711 var s = S{ .f0 = 0 };
712 _ = &s;
713 comptime assert(s.f0 == 0);
714}
715
716test "access to global struct fields" {
717 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
718
719 g_foo.bar.value = 42;
720 try expect(g_foo.bar.value == 42);
721}
722
723const S0 = struct {
724 bar: S1,
725
726 pub const S1 = struct {
727 value: u8,
728 };
729
730 fn init() @This() {
731 return S0{ .bar = S1{ .value = 123 } };
732 }
733};
734
735var g_foo: S0 = S0.init();
736
737test "packed struct with fp fields" {
738 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
740 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
741 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
742 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
743
744 const S = packed struct {
745 data0: f32,
746 data1: f32,
747 data2: f32,
748
749 pub fn frob(self: *@This()) void {
750 self.data0 += self.data1 + self.data2;
751 self.data1 += self.data0 + self.data2;
752 self.data2 += self.data0 + self.data1;
753 }
754 };
755
756 var s: S = undefined;
757 s.data0 = 1.0;
758 s.data1 = 2.0;
759 s.data2 = 3.0;
760 s.frob();
761 try expect(@as(f32, 6.0) == s.data0);
762 try expect(@as(f32, 11.0) == s.data1);
763 try expect(@as(f32, 20.0) == s.data2);
764}
765
766test "fn with C calling convention returns struct by value" {
767 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
768 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
769
770 const S = struct {
771 fn entry() !void {
772 const x = makeBar(10);
773 try expect(@as(i32, 10) == x.handle);
774 }
775
776 const ExternBar = extern struct {
777 handle: i32,
778 };
779
780 fn makeBar(t: i32) callconv(.c) ExternBar {
781 return ExternBar{
782 .handle = t,
783 };
784 }
785 };
786 try S.entry();
787 try comptime S.entry();
788}
789
790test "non-packed struct with u128 entry in union" {
791 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
793 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
794 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
795
796 const U = union(enum) {
797 Num: u128,
798 Void,
799 };
800
801 const S = struct {
802 f1: U,
803 f2: U,
804 };
805
806 var sx: S = undefined;
807 var s = &sx;
808 try expect(@intFromPtr(&s.f2) - @intFromPtr(&s.f1) == @offsetOf(S, "f2"));
809 var v2 = U{ .Num = 123 };
810 _ = &v2;
811 s.f2 = v2;
812 try expect(s.f2.Num == 123);
813}
814
815test "packed struct field passed to generic function" {
816 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
818 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
819
820 const S = struct {
821 const P = packed struct {
822 b: u5,
823 g: u5,
824 r: u5,
825 a: u1,
826 };
827
828 fn genericReadPackedField(ptr: anytype) u5 {
829 return ptr.*;
830 }
831 };
832
833 var p: S.P = undefined;
834 p.b = 29;
835 const loaded = S.genericReadPackedField(&p.b);
836 try expect(loaded == 29);
837}
838
839test "anonymous struct literal syntax" {
840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
841
842 const S = struct {
843 const Point = struct {
844 x: i32,
845 y: i32,
846 };
847
848 fn doTheTest() !void {
849 var p: Point = .{
850 .x = 1,
851 .y = 2,
852 };
853 _ = &p;
854 try expect(p.x == 1);
855 try expect(p.y == 2);
856 }
857 };
858 try S.doTheTest();
859 try comptime S.doTheTest();
860}
861
862test "fully anonymous struct" {
863 const S = struct {
864 fn doTheTest() !void {
865 try dump(.{
866 .int = @as(u32, 1234),
867 .float = @as(f64, 12.34),
868 .b = true,
869 .s = "hi",
870 });
871 }
872 fn dump(args: anytype) !void {
873 try expect(args.int == 1234);
874 try expect(args.float == 12.34);
875 try expect(args.b);
876 try expect(args.s[0] == 'h');
877 try expect(args.s[1] == 'i');
878 }
879 };
880 try S.doTheTest();
881 try comptime S.doTheTest();
882}
883
884test "fully anonymous list literal" {
885 const S = struct {
886 fn doTheTest() !void {
887 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
888 }
889 fn dump(args: anytype) !void {
890 try expect(args.@"0" == 1234);
891 try expect(args.@"1" == 12.34);
892 try expect(args.@"2");
893 try expect(args.@"3"[0] == 'h');
894 try expect(args.@"3"[1] == 'i');
895 }
896 };
897 try S.doTheTest();
898 try comptime S.doTheTest();
899}
900
901test "tuple assigned to variable" {
902 var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
903 _ = &vec;
904 try expect(vec.@"0" == 22);
905 try expect(vec.@"1" == 55);
906 try expect(vec.@"2" == 99);
907 try expect(vec[0] == 22);
908 try expect(vec[1] == 55);
909 try expect(vec[2] == 99);
910}
911
912test "comptime struct field" {
913 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
914
915 const T = struct {
916 a: i32,
917 comptime b: i32 = 1234,
918 };
919
920 comptime std.debug.assert(@sizeOf(T) == 4);
921
922 var foo: T = undefined;
923 _ = &foo;
924 comptime assert(foo.b == 1234);
925}
926
927test "tuple element initialized with fn call" {
928 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
929 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
931
932 const S = struct {
933 fn doTheTest() !void {
934 const x = .{foo()};
935 try expectEqualSlices(u8, x[0], "hi");
936 }
937 fn foo() []const u8 {
938 return "hi";
939 }
940 };
941 try S.doTheTest();
942 try comptime S.doTheTest();
943}
944
945test "struct with union field" {
946 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
948 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
949
950 const Value = struct {
951 ref: u32 = 2,
952 kind: union(enum) {
953 None: usize,
954 Bool: bool,
955 },
956 };
957
958 var True = Value{
959 .kind = .{ .Bool = true },
960 };
961 _ = &True;
962 try expect(@as(u32, 2) == True.ref);
963 try expect(True.kind.Bool);
964}
965
966test "struct with 0-length union array field" {
967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
968 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
969
970 const U = union {
971 a: u32,
972 b: u64,
973 };
974
975 const S = struct {
976 zero_length: [0]U,
977 };
978
979 var s: S = undefined;
980 _ = &s;
981 try expectEqual(@as(usize, 0), s.zero_length.len);
982}
983
984test "packed struct with undefined initializers" {
985 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
986 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
988 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
989
990 const S = struct {
991 const P = packed struct {
992 a: u3,
993 _a: u3 = undefined,
994 b: u3,
995 _b: u3 = undefined,
996 c: u3,
997 _c: u3 = undefined,
998 };
999
1000 fn doTheTest() !void {
1001 var p: P = undefined;
1002 p = P{ .a = 2, .b = 4, .c = 6 };
1003 // Make sure the compiler doesn't touch the unprefixed fields.
1004 // Use expect since x86-linux doesn't like expectEqual
1005 try expect(p.a == 2);
1006 try expect(p.b == 4);
1007 try expect(p.c == 6);
1008 }
1009 };
1010
1011 try S.doTheTest();
1012 try comptime S.doTheTest();
1013}
1014
1015test "for loop over pointers to struct, getting field from struct pointer" {
1016 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1019
1020 const S = struct {
1021 const Foo = struct {
1022 name: []const u8,
1023 };
1024
1025 var ok = true;
1026
1027 fn eql(a: []const u8) bool {
1028 _ = a;
1029 return true;
1030 }
1031
1032 const ArrayList = struct {
1033 fn toSlice(self: *ArrayList) []*Foo {
1034 _ = self;
1035 return @as([*]*Foo, undefined)[0..0];
1036 }
1037 };
1038
1039 fn doTheTest() !void {
1040 var objects: ArrayList = undefined;
1041
1042 for (objects.toSlice()) |obj| {
1043 if (eql(obj.name)) {
1044 ok = false;
1045 }
1046 }
1047
1048 try expect(ok);
1049 }
1050 };
1051 try S.doTheTest();
1052}
1053
1054test "anon init through error unions and optionals" {
1055 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1056 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1058 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1059
1060 const S = struct {
1061 a: u32,
1062
1063 fn foo() anyerror!?anyerror!@This() {
1064 return .{ .a = 1 };
1065 }
1066 fn bar() ?anyerror![2]u8 {
1067 return .{ 1, 2 };
1068 }
1069
1070 fn doTheTest() !void {
1071 const a = try (try foo()).?;
1072 const b = try bar().?;
1073 try expect(a.a + b[1] == 3);
1074 }
1075 };
1076
1077 try S.doTheTest();
1078 try comptime S.doTheTest();
1079}
1080
1081test "anon init through optional" {
1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1083 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1084 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1085
1086 const S = struct {
1087 a: u32,
1088
1089 fn doTheTest() !void {
1090 var s: ?@This() = null;
1091 s = .{ .a = 1 };
1092 try expect(s.?.a == 1);
1093 }
1094 };
1095
1096 try S.doTheTest();
1097 try comptime S.doTheTest();
1098}
1099
1100test "anon init through error union" {
1101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1103 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1104
1105 const S = struct {
1106 a: u32,
1107
1108 fn doTheTest() !void {
1109 var s: anyerror!@This() = error.Foo;
1110 s = .{ .a = 1 };
1111 try expect((try s).a == 1);
1112 }
1113 };
1114
1115 try S.doTheTest();
1116 try comptime S.doTheTest();
1117}
1118
1119test "typed init through error unions and optionals" {
1120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1121 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1122 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1123
1124 const S = struct {
1125 a: u32,
1126
1127 fn foo() anyerror!?anyerror!@This() {
1128 return @This(){ .a = 1 };
1129 }
1130 fn bar() ?anyerror![2]u8 {
1131 return [2]u8{ 1, 2 };
1132 }
1133
1134 fn doTheTest() !void {
1135 const a = try (try foo()).?;
1136 const b = try bar().?;
1137 try expect(a.a + b[1] == 3);
1138 }
1139 };
1140
1141 try S.doTheTest();
1142 try comptime S.doTheTest();
1143}
1144
1145test "initialize struct with empty literal" {
1146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1147
1148 const S = struct { x: i32 = 1234 };
1149 var s: S = .{};
1150 _ = &s;
1151 try expect(s.x == 1234);
1152}
1153
1154test "loading a struct pointer perfoms a copy" {
1155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1156
1157 const S = struct {
1158 a: i32,
1159 b: i32,
1160 c: i32,
1161
1162 fn swap(a: *@This(), b: *@This()) void {
1163 const tmp = a.*;
1164 a.* = b.*;
1165 b.* = tmp;
1166 }
1167 };
1168 var s1: S = .{ .a = 1, .b = 2, .c = 3 };
1169 var s2: S = .{ .a = 4, .b = 5, .c = 6 };
1170 S.swap(&s1, &s2);
1171 try expect(s1.a == 4);
1172 try expect(s1.b == 5);
1173 try expect(s1.c == 6);
1174 try expect(s2.a == 1);
1175 try expect(s2.b == 2);
1176 try expect(s2.c == 3);
1177}
1178
1179test "packed struct aggregate init" {
1180 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1183 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1184
1185 const S = struct {
1186 fn foo(a: i2, b: i6) u8 {
1187 return @as(u8, @bitCast(P{ .a = a, .b = b }));
1188 }
1189
1190 const P = packed struct {
1191 a: i2,
1192 b: i6,
1193 };
1194 };
1195 const result = @as(u8, @bitCast(S.foo(1, 2)));
1196 try expect(result == 9);
1197}
1198
1199test "packed struct field access via pointer" {
1200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1203
1204 const S = struct {
1205 fn doTheTest() !void {
1206 const S = packed struct { a: u30 };
1207 var s1: S = .{ .a = 1 };
1208 const s2 = &s1;
1209 try expect(s2.a == 1);
1210 var s3: S = undefined;
1211 const s4 = &s3;
1212 _ = s4;
1213 }
1214 };
1215 try S.doTheTest();
1216 try comptime S.doTheTest();
1217}
1218
1219test "store to comptime field" {
1220 {
1221 const S = struct {
1222 comptime a: [2]u32 = [2]u32{ 1, 2 },
1223 };
1224 var s: S = .{};
1225 s.a = [2]u32{ 1, 2 };
1226 s.a[0] = 1;
1227 }
1228 {
1229 const T = struct { a: u32, b: u32 };
1230 const S = struct {
1231 comptime a: T = T{ .a = 1, .b = 2 },
1232 };
1233 var s: S = .{};
1234 s.a = T{ .a = 1, .b = 2 };
1235 s.a.a = 1;
1236 }
1237}
1238
1239test "struct field init value is size of the struct" {
1240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1241
1242 const namespace = struct {
1243 const S = extern struct {
1244 size: u8 = @sizeOf(S),
1245 blah: u16,
1246 };
1247 };
1248 var s: namespace.S = .{ .blah = 1234 };
1249 _ = &s;
1250 try expect(s.size == 4);
1251}
1252
1253test "under-aligned struct field" {
1254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1256 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1257 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1258
1259 const U = extern union {
1260 fd: i32,
1261 u32: u32,
1262 u64: u64,
1263 };
1264 const S = extern struct {
1265 events: u32,
1266 data: U align(4),
1267 };
1268 var runtime: usize = 1234;
1269 _ = &runtime;
1270 const ptr = &S{ .events = 0, .data = .{ .u64 = runtime } };
1271 const array = @as(*const [12]u8, @ptrCast(ptr));
1272 const result = std.mem.readInt(u64, array[4..12], native_endian);
1273 try expect(result == 1234);
1274}
1275
1276test "fieldParentPtr of a zero-bit field" {
1277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1278 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1279 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1280
1281 const S = struct {
1282 fn testStruct(comptime A: type) !void {
1283 {
1284 const a = A{ .u = 0 };
1285 const b_ptr = &a.b;
1286 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1287 try std.testing.expectEqual(&a, a_ptr);
1288 }
1289 {
1290 var a = A{ .u = 0 };
1291 const b_ptr = &a.b;
1292 const a_ptr: *A = @fieldParentPtr("b", b_ptr);
1293 try std.testing.expectEqual(&a, a_ptr);
1294 }
1295 }
1296 fn testNestedStruct(comptime A: type) !void {
1297 {
1298 const a = A{ .u = 0 };
1299 const c_ptr = &a.b.c;
1300 const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr);
1301 try std.testing.expectEqual(&a.b, b_ptr);
1302 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1303 try std.testing.expectEqual(&a, a_ptr);
1304 }
1305 {
1306 var a = A{ .u = 0 };
1307 const c_ptr = &a.b.c;
1308 const b_ptr: @TypeOf(&a.b) = @fieldParentPtr("c", c_ptr);
1309 try std.testing.expectEqual(&a.b, b_ptr);
1310 const a_ptr: *const A = @fieldParentPtr("b", b_ptr);
1311 try std.testing.expectEqual(&a, a_ptr);
1312 }
1313 }
1314 fn doTheTest() !void {
1315 try testStruct(struct { b: void = {}, u: u8 });
1316 try testStruct(struct { u: u8, b: void = {} });
1317 try testNestedStruct(struct { b: struct { c: void = {} } = .{}, u: u8 });
1318 try testNestedStruct(struct { u: u8, b: struct { c: void = {} } = .{} });
1319 }
1320 };
1321 try S.doTheTest();
1322 try comptime S.doTheTest();
1323}
1324
1325test "struct field has a pointer to an aligned version of itself" {
1326 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1327
1328 const E = struct {
1329 next: *align(1) @This(),
1330 };
1331 var e: E = undefined;
1332 e = .{ .next = &e };
1333
1334 try expect(&e == e.next);
1335}
1336
1337test "struct has only one reference" {
1338 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1339
1340 const S = struct {
1341 fn optionalStructParam(_: ?struct { x: u8 }) void {}
1342 fn errorUnionStructParam(_: error{}!struct { x: u8 }) void {}
1343 fn optionalStructReturn() ?struct { x: u8 } {
1344 return null;
1345 }
1346 fn errorUnionStructReturn() error{Foo}!struct { x: u8 } {
1347 return error.Foo;
1348 }
1349
1350 fn pointerPackedStruct(_: *packed struct { x: u8 }) void {}
1351 fn nestedPointerPackedStruct(_: struct { x: *packed struct { x: u8 } }) void {}
1352 fn pointerNestedPackedStruct(_: *struct { x: packed struct { x: u8 } }) void {}
1353 fn pointerNestedPointerPackedStruct(_: *struct { x: *packed struct { x: u8 } }) void {}
1354
1355 fn optionalComptimeIntParam(comptime x: ?comptime_int) comptime_int {
1356 return x.?;
1357 }
1358 fn errorUnionComptimeIntParam(comptime x: error{}!comptime_int) comptime_int {
1359 return x catch unreachable;
1360 }
1361 };
1362
1363 const optional_struct_param: *const anyopaque = &S.optionalStructParam;
1364 const error_union_struct_param: *const anyopaque = &S.errorUnionStructParam;
1365 try expect(optional_struct_param != error_union_struct_param);
1366
1367 const optional_struct_return: *const anyopaque = &S.optionalStructReturn;
1368 const error_union_struct_return: *const anyopaque = &S.errorUnionStructReturn;
1369 try expect(optional_struct_return != error_union_struct_return);
1370
1371 const pointer_packed_struct: *const anyopaque = &S.pointerPackedStruct;
1372 const nested_pointer_packed_struct: *const anyopaque = &S.nestedPointerPackedStruct;
1373 try expect(pointer_packed_struct != nested_pointer_packed_struct);
1374
1375 const pointer_nested_packed_struct: *const anyopaque = &S.pointerNestedPackedStruct;
1376 const pointer_nested_pointer_packed_struct: *const anyopaque = &S.pointerNestedPointerPackedStruct;
1377 try expect(pointer_nested_packed_struct != pointer_nested_pointer_packed_struct);
1378
1379 try expectEqual(@alignOf(struct {}), S.optionalComptimeIntParam(@alignOf(struct {})));
1380 try expectEqual(@alignOf(struct { x: u8 }), S.errorUnionComptimeIntParam(@alignOf(struct { x: u8 })));
1381 try expectEqual(@sizeOf(struct { x: u16 }), S.optionalComptimeIntParam(@sizeOf(struct { x: u16 })));
1382 try expectEqual(@sizeOf(struct { x: u32 }), S.errorUnionComptimeIntParam(@sizeOf(struct { x: u32 })));
1383}
1384
1385test "no dependency loop on pointer to optional struct" {
1386 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1387 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1388
1389 const S = struct {
1390 const A = struct { b: B };
1391 const B = struct { a: *?A };
1392 };
1393 var a1: ?S.A = null;
1394 var a2: ?S.A = .{ .b = .{ .a = &a1 } };
1395 a1 = .{ .b = .{ .a = &a2 } };
1396
1397 try expect(a1.?.b.a == &a2);
1398 try expect(a2.?.b.a == &a1);
1399}
1400
1401test "discarded struct initialization works as expected" {
1402 const S = struct { a: u32 };
1403 _ = S{ .a = 1 };
1404}
1405
1406test "function pointer in struct returns the struct" {
1407 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1408
1409 const A = struct {
1410 const A = @This();
1411 ptr: *const fn () A,
1412
1413 fn f() A {
1414 return .{ .ptr = f };
1415 }
1416 };
1417 var a = A.f();
1418 _ = &a;
1419 try expect(a.ptr == A.f);
1420}
1421
1422test "no dependency loop on optional field wrapped in generic function" {
1423 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1424
1425 const S = struct {
1426 fn Atomic(comptime T: type) type {
1427 return T;
1428 }
1429 const A = struct { b: Atomic(?*B) };
1430 const B = struct { a: ?*A };
1431 };
1432 var a: S.A = .{ .b = null };
1433 var b: S.B = .{ .a = &a };
1434 a.b = &b;
1435
1436 try expect(a.b == &b);
1437 try expect(b.a == &a);
1438}
1439
1440test "optional field init with tuple" {
1441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1442
1443 const S = struct {
1444 a: ?struct { b: u32 },
1445 };
1446 var a: u32 = 0;
1447 _ = &a;
1448 const b = S{
1449 .a = .{ .b = a },
1450 };
1451 try expect(b.a.?.b == a);
1452}
1453
1454test "if inside struct init inside if" {
1455 const MyStruct = struct { x: u32 };
1456 const b: u32 = 5;
1457 var i: u32 = 1;
1458 _ = &i;
1459 const my_var = if (i < 5)
1460 MyStruct{
1461 .x = 1 + if (i > 0) b else 0,
1462 }
1463 else
1464 MyStruct{
1465 .x = 1 + if (i > 0) b else 0,
1466 };
1467 try expect(my_var.x == 6);
1468}
1469
1470test "optional generic function label struct field" {
1471 const Options = struct {
1472 isFoo: ?fn (comptime type) u8 = defaultIsFoo,
1473 fn defaultIsFoo(comptime _: type) u8 {
1474 return 123;
1475 }
1476 };
1477 try expect((Options{}).isFoo.?(u8) == 123);
1478}
1479
1480test "struct fields get automatically reordered" {
1481 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1482 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1483
1484 const S1 = struct {
1485 a: u32,
1486 b: u32,
1487 c: bool,
1488 d: bool,
1489 };
1490 const S2 = struct {
1491 a: u32,
1492 b: bool,
1493 c: u32,
1494 d: bool,
1495 };
1496 try expect(@sizeOf(S1) == @sizeOf(S2));
1497}
1498
1499test "directly initiating tuple like struct" {
1500 const a = struct { u8 }{8};
1501 try expect(a[0] == 8);
1502}
1503
1504test "instantiate struct with comptime field" {
1505 {
1506 var things = struct {
1507 comptime foo: i8 = 1,
1508 }{};
1509 _ = &things;
1510 comptime std.debug.assert(things.foo == 1);
1511 }
1512
1513 {
1514 const T = struct {
1515 comptime foo: i8 = 1,
1516 };
1517 var things = T{};
1518 _ = &things;
1519 comptime std.debug.assert(things.foo == 1);
1520 }
1521
1522 {
1523 var things: struct {
1524 comptime foo: i8 = 1,
1525 } = .{};
1526 _ = &things;
1527 comptime std.debug.assert(things.foo == 1);
1528 }
1529
1530 {
1531 var things: struct {
1532 comptime foo: i8 = 1,
1533 } = undefined; // Segmentation fault at address 0x0
1534 _ = &things;
1535 comptime std.debug.assert(things.foo == 1);
1536 }
1537}
1538
1539test "struct field pointer has correct alignment" {
1540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1542 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1543
1544 const S = struct {
1545 fn doTheTest() !void {
1546 var a: struct { x: u32 } = .{ .x = 123 };
1547 var b: struct { x: u32 } align(1) = .{ .x = 456 };
1548 var c: struct { x: u32 } align(64) = .{ .x = 789 };
1549
1550 const ap = &a.x;
1551 const bp = &b.x;
1552 const cp = &c.x;
1553
1554 comptime assert(@TypeOf(ap) == *u32);
1555 comptime assert(@TypeOf(bp) == *align(1) u32);
1556 comptime assert(@TypeOf(cp) == *u32); // undefined layout, cannot inherit larger alignment
1557
1558 try expectEqual(@as(u32, 123), ap.*);
1559 try expectEqual(@as(u32, 456), bp.*);
1560 try expectEqual(@as(u32, 789), cp.*);
1561 }
1562 };
1563
1564 try S.doTheTest();
1565 try comptime S.doTheTest();
1566}
1567
1568test "extern struct field pointer has correct alignment" {
1569 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1570 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1572
1573 const S = struct {
1574 fn doTheTest() !void {
1575 var a: extern struct { x: u32, y: u16 } = .{ .x = 1, .y = 2 };
1576 var b: extern struct { x: u32, y: u16 } align(1) = .{ .x = 3, .y = 4 };
1577 var c: extern struct { x: u32, y: u16 } align(64) = .{ .x = 5, .y = 6 };
1578
1579 const axp = &a.x;
1580 const bxp = &b.x;
1581 const cxp = &c.x;
1582 const ayp = &a.y;
1583 const byp = &b.y;
1584 const cyp = &c.y;
1585
1586 comptime assert(@TypeOf(axp) == *u32);
1587 comptime assert(@TypeOf(bxp) == *align(1) u32);
1588 comptime assert(@TypeOf(cxp) == *align(64) u32);
1589
1590 comptime assert(@TypeOf(ayp) == *align(@alignOf(u32)) u16);
1591 comptime assert(@TypeOf(byp) == *align(1) u16);
1592 comptime assert(@TypeOf(cyp) == *align(@alignOf(u32)) u16);
1593
1594 try expectEqual(@as(u32, 1), axp.*);
1595 try expectEqual(@as(u32, 3), bxp.*);
1596 try expectEqual(@as(u32, 5), cxp.*);
1597
1598 try expectEqual(@as(u16, 2), ayp.*);
1599 try expectEqual(@as(u16, 4), byp.*);
1600 try expectEqual(@as(u16, 6), cyp.*);
1601 }
1602 };
1603
1604 try S.doTheTest();
1605 try comptime S.doTheTest();
1606}
1607
1608test "packed struct field in anonymous struct" {
1609 const T = packed struct {
1610 f1: bool = false,
1611 };
1612
1613 try std.testing.expect(countFields(.{ .t = T{} }) == 1);
1614}
1615fn countFields(v: anytype) usize {
1616 return @typeInfo(@TypeOf(v)).@"struct".field_names.len;
1617}
1618
1619test "struct init with no result pointer sets field result types" {
1620 const S = struct {
1621 // A function parameter has a result type, but no result pointer.
1622 fn f(s: struct { x: u32 }) u32 {
1623 return s.x;
1624 }
1625 };
1626
1627 const x: u64 = 123;
1628 const y = S.f(.{ .x = @intCast(x) });
1629
1630 try expect(y == x);
1631}
1632
1633test "runtime side-effects in comptime-known struct init" {
1634 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1635
1636 var side_effects: u4 = 0;
1637 const S = struct { a: u4, b: u4, c: u4, d: u4 };
1638 const init = S{
1639 .d = blk: {
1640 side_effects += 8;
1641 break :blk 8;
1642 },
1643 .c = blk: {
1644 side_effects += 4;
1645 break :blk 4;
1646 },
1647 .b = blk: {
1648 side_effects += 2;
1649 break :blk 2;
1650 },
1651 .a = blk: {
1652 side_effects += 1;
1653 break :blk 1;
1654 },
1655 };
1656 try expectEqual(S{ .a = 1, .b = 2, .c = 4, .d = 8 }, init);
1657 try expectEqual(@as(u4, std.math.maxInt(u4)), side_effects);
1658}
1659
1660test "pointer to struct initialized through reference to anonymous initializer provides result types" {
1661 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1662
1663 const S = struct { a: u8, b: u16, c: *const anyopaque };
1664 var my_u16: u16 = 0xABCD;
1665 _ = &my_u16;
1666 const s: *const S = &.{
1667 // intentionally out of order
1668 .c = @ptrCast("hello"),
1669 .b = my_u16,
1670 .a = @truncate(my_u16),
1671 };
1672 try expect(s.a == 0xCD);
1673 try expect(s.b == 0xABCD);
1674 const str: *const [5]u8 = @ptrCast(s.c);
1675 try std.testing.expectEqualSlices(u8, "hello", str);
1676}
1677
1678test "comptimeness of optional and error union payload is analyzed properly" {
1679 // This is primarily a semantic analysis integrity test.
1680 // The original failure mode for this was a crash.
1681 // Both structs and unions work for this, the point is that
1682 // their comptimeness is lazily evaluated.
1683 const S = struct {};
1684 // Original form of bug #17511, regressed in #17471
1685 const a = @sizeOf(?*S);
1686 _ = a;
1687 // Error union case, fails assertion in debug versions of release 0.11.0
1688 _ = @sizeOf(anyerror!*S);
1689 _ = @sizeOf(anyerror!?S);
1690 // Evaluation case, crashes the actual release 0.11.0
1691 const C = struct { x: comptime_int };
1692 const c: anyerror!?C = .{ .x = 3 };
1693 const x = (try c).?.x;
1694 try std.testing.expectEqual(3, x);
1695}
1696
1697test "initializer uses own alignment" {
1698 const S = struct {
1699 x: u32 = @alignOf(@This()) + 1,
1700 };
1701
1702 var s: S = .{};
1703 _ = &s;
1704 try expectEqual(4, @alignOf(S));
1705 try expectEqual(@as(usize, 5), s.x);
1706}
1707
1708test "initializer uses own size" {
1709 const S = struct {
1710 x: u32 = @sizeOf(@This()) + 1,
1711 };
1712
1713 var s: S = .{};
1714 _ = &s;
1715 try expectEqual(4, @sizeOf(S));
1716 try expectEqual(@as(usize, 5), s.x);
1717}
1718
1719test "initializer takes a pointer to a variable inside its struct" {
1720 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1721
1722 const namespace = struct {
1723 const S = struct {
1724 s: *S = &S.instance,
1725 var instance: S = undefined;
1726 };
1727
1728 fn doTheTest() !void {
1729 var foo: S = .{};
1730 _ = &foo;
1731 try expectEqual(&S.instance, foo.s);
1732 }
1733 };
1734
1735 try namespace.doTheTest();
1736 comptime try namespace.doTheTest();
1737}
1738
1739test "circular dependency through pointer field of a struct" {
1740 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1741
1742 const S = struct {
1743 const StructInner = extern struct {
1744 outer: StructOuter = std.mem.zeroes(StructOuter),
1745 };
1746
1747 const StructMiddle = extern struct {
1748 outer: ?*StructInner,
1749 inner: ?*StructOuter,
1750 };
1751
1752 const StructOuter = extern struct {
1753 middle: StructMiddle = std.mem.zeroes(StructMiddle),
1754 };
1755 };
1756 var outer: S.StructOuter = .{};
1757 _ = &outer;
1758 try expect(outer.middle.outer == null);
1759 try expect(outer.middle.inner == null);
1760}
1761
1762test "field calls do not force struct field init resolution" {
1763 const S = struct {
1764 x: u32 = blk: {
1765 _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution
1766 break :blk 123;
1767 },
1768 dummyFn: *const fn () void = undefined,
1769 fn make() @This() {
1770 return .{};
1771 }
1772 };
1773 var s: S = .{};
1774 _ = &s;
1775 try expect(s.x == 123);
1776}
1777
1778test "tuple with comptime-only field" {
1779 const S = struct {
1780 fn getTuple() struct { comptime_int } {
1781 return struct { comptime comptime_int = 0 }{0};
1782 }
1783 };
1784
1785 const x = S.getTuple();
1786 try expect(x.@"0" == 0);
1787}
1788
1789test "extern struct fields are aligned to 1" {
1790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1791
1792 const Foo = extern struct {
1793 a: u8 align(1),
1794 b: u16 align(1),
1795 };
1796
1797 const foo = Foo{
1798 .a = 1,
1799 .b = 2,
1800 };
1801 try std.testing.expectEqual(1, foo.a);
1802 try std.testing.expectEqual(2, foo.b);
1803}
1804
1805test "assign to slice.len of global variable" {
1806 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1807 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1808 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1810 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1811
1812 const S = struct {
1813 const allocator = std.testing.allocator;
1814 var list = std.array_list.Managed(u32).init(allocator);
1815 };
1816
1817 S.list.items.len = 0;
1818 try expect(S.list.items.len == 0);
1819}
1820
1821test "pointers to fields of volatile pointer to struct are also volatile" {
1822 const B = extern struct {
1823 a: u32,
1824 b: i32,
1825 };
1826 const A = extern struct {
1827 value: *volatile B,
1828 };
1829
1830 var a: *A = undefined;
1831 try expect(@TypeOf(&a.value.a) == *volatile u32);
1832 try expect(@TypeOf(&a.value.b) == *volatile i32);
1833}
1834
1835test "pointers to fields of volatile pointer to union are also volatile" {
1836 const D = extern union {
1837 a: u32,
1838 b: i32,
1839 };
1840 const C = extern struct {
1841 value: *volatile D,
1842 };
1843
1844 var c: *C = undefined;
1845 try expect(@TypeOf(&c.value.a) == *volatile u32);
1846 try expect(@TypeOf(&c.value.b) == *volatile i32);
1847}
1848
1849test "array of structs inside struct initialized with undefined" {
1850 const Item = struct { field: u8 };
1851 const Thing = struct {
1852 array: [1]Item,
1853 };
1854 _ = Thing{ .array = undefined };
1855}
1856
1857test "runtime call in nested initializer" {
1858 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1859 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1860
1861 const Holder = struct {
1862 array: []const u8,
1863 };
1864 const Test = struct {
1865 holders: []const Holder,
1866 };
1867 const Letter = enum(u8) {
1868 A = 0x41,
1869 B,
1870
1871 fn letter(e: @This()) u8 {
1872 return @backingInt(e);
1873 }
1874 };
1875
1876 const test_struct = Test{
1877 .holders = &.{
1878 Holder{
1879 .array = &.{
1880 Letter.letter(.A),
1881 },
1882 },
1883 },
1884 };
1885 try std.testing.expectEqualStrings("A", test_struct.holders[0].array);
1886}
1887
1888test "runtime value in nested initializer passed as pointer to function" {
1889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1890
1891 const Bar = struct {
1892 b: u32,
1893 };
1894 const Foo = struct {
1895 a: Bar,
1896
1897 fn takeFoo(foo: *const @This()) !void {
1898 try std.testing.expectEqual(@as(u32, 24), foo.a.b);
1899 }
1900 };
1901
1902 var baz: u32 = 24;
1903 _ = &baz;
1904 try Foo.takeFoo(&.{
1905 .a = .{
1906 .b = baz,
1907 },
1908 });
1909}
1910
1911test "struct field default value is a call" {
1912 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1913 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1914 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1915
1916 const Z = packed struct {
1917 a: u32,
1918 };
1919 const Y = struct {
1920 a: u16,
1921 b: bool,
1922 c: Z,
1923 d: Z,
1924
1925 fn init() @This() {
1926 return .{
1927 .a = 0,
1928 .b = false,
1929 .c = @as(Z, @bitCast(@as(u32, 0))),
1930 .d = @as(Z, @bitCast(@as(u32, 0))),
1931 };
1932 }
1933 };
1934 const X = struct {
1935 y: Y = Y.init(),
1936 };
1937
1938 const x = X{};
1939 try std.testing.expectEqual(@as(u16, 0), x.y.a);
1940 try std.testing.expectEqual(false, x.y.b);
1941 try std.testing.expectEqual(Z{ .a = 0 }, x.y.c);
1942 try std.testing.expectEqual(Z{ .a = 0 }, x.y.d);
1943}
1944
1945test "aggregate initializers should allow initializing comptime fields, verifying equality" {
1946 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1947
1948 var x: u32 = 15;
1949 _ = &x;
1950 const T = @TypeOf(.{ @as(i32, -1234), @as(u32, 5678), x });
1951 const a: T = .{ -1234, 5678, x + 1 };
1952
1953 try expect(a[0] == -1234);
1954 try expect(a[1] == 5678);
1955 try expect(a[2] == 16);
1956}
1957
1958test "assignment of field with padding" {
1959 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1960 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1961
1962 const Mesh = extern struct {
1963 id: u32,
1964 };
1965 const Material = extern struct {
1966 transparent: bool = true,
1967 emits_shadows: bool = true,
1968 render_color: bool = true,
1969 };
1970 const Renderable = extern struct {
1971 material: Material,
1972 mesh: Mesh,
1973 };
1974 var renderable: Renderable = undefined;
1975 renderable = Renderable{
1976 .mesh = Mesh{ .id = 0 },
1977 .material = Material{
1978 .transparent = false,
1979 .emits_shadows = false,
1980 },
1981 };
1982 try expect(false == renderable.material.transparent);
1983 try expect(false == renderable.material.emits_shadows);
1984 try expect(true == renderable.material.render_color);
1985}
1986
1987test "initiate global variable with runtime value" {
1988 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1989 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1990
1991 const S = struct {
1992 field: i32,
1993 fn couldFail() anyerror!i32 {
1994 return 1;
1995 }
1996 var some_struct: @This() = undefined;
1997 };
1998
1999 S.some_struct = .{
2000 .field = S.couldFail() catch 0,
2001 };
2002 try expect(S.some_struct.field == 1);
2003}
2004
2005test "struct containing optional pointer to array of @This()" {
2006 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2007
2008 const S = struct {
2009 x: ?*const [1]@This(),
2010 };
2011
2012 var s: S = .{ .x = &.{.{ .x = null }} };
2013 _ = &s;
2014 try expect(s.x.?[0].x == null);
2015}
2016
2017test "matching captures causes struct equivalence" {
2018 const S = struct {
2019 fn UnsignedWrapper(comptime I: type) type {
2020 const bits = @typeInfo(I).int.bits;
2021 return struct {
2022 x: @Int(.unsigned, bits),
2023 };
2024 }
2025 };
2026
2027 comptime assert(S.UnsignedWrapper(u8) == S.UnsignedWrapper(i8));
2028 comptime assert(S.UnsignedWrapper(u16) == S.UnsignedWrapper(i16));
2029 comptime assert(S.UnsignedWrapper(u8) != S.UnsignedWrapper(u16));
2030
2031 const a: S.UnsignedWrapper(u8) = .{ .x = 10 };
2032 const b: S.UnsignedWrapper(i8) = .{ .x = 10 };
2033 comptime assert(@TypeOf(a) == @TypeOf(b));
2034 try expect(a.x == b.x);
2035}
2036
2037test "struct @FieldType" {
2038 const S = struct {
2039 a: u32,
2040 b: f64,
2041 c: *@This(),
2042 };
2043
2044 comptime assert(@FieldType(S, "a") == u32);
2045 comptime assert(@FieldType(S, "b") == f64);
2046 comptime assert(@FieldType(S, "c") == *S);
2047}
2048
2049test "extern struct @FieldType" {
2050 const S = extern struct {
2051 a: u32,
2052 b: f64,
2053 c: *@This(),
2054 };
2055
2056 comptime assert(@FieldType(S, "a") == u32);
2057 comptime assert(@FieldType(S, "b") == f64);
2058 comptime assert(@FieldType(S, "c") == *S);
2059}
2060
2061test "anonymous struct equivalence" {
2062 const S = struct {
2063 fn anonStructType(comptime x: anytype) type {
2064 const val = .{ .a = "hello", .b = x };
2065 return @TypeOf(val);
2066 }
2067 };
2068
2069 const A = S.anonStructType(123);
2070 const B = S.anonStructType(123);
2071 const C = S.anonStructType(456);
2072
2073 comptime assert(A == B);
2074 comptime assert(A != C);
2075 comptime assert(B != C);
2076}
2077
2078test "field access through mem ptr arg" {
2079 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2080 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2081
2082 const S = struct {
2083 fn nestedFieldAccess(
2084 _: usize,
2085 _: usize,
2086 _: usize,
2087 _: usize,
2088 _: usize,
2089 _: usize,
2090 _: usize,
2091 _: usize,
2092 ptr_struct: *const struct { field: u32 },
2093 ) u32 {
2094 return ptr_struct.field;
2095 }
2096 };
2097 try expect(S.nestedFieldAccess(
2098 undefined,
2099 undefined,
2100 undefined,
2101 undefined,
2102 undefined,
2103 undefined,
2104 undefined,
2105 undefined,
2106 &.{ .field = 0x6b00a2eb },
2107 ) == 0x6b00a2eb);
2108 comptime assert(S.nestedFieldAccess(
2109 undefined,
2110 undefined,
2111 undefined,
2112 undefined,
2113 undefined,
2114 undefined,
2115 undefined,
2116 undefined,
2117 &.{ .field = 0x0ced271f },
2118 ) == 0x0ced271f);
2119}
2120
2121test "align 1 struct parameter dereferenced and returned" {
2122 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2123
2124 const S = extern struct {
2125 a: u32,
2126
2127 fn gimme(p: *align(1) @This()) @This() {
2128 return p.*;
2129 }
2130 };
2131 var buffer: [5]u8 align(4) = .{ 1, 2, 3, 4, 5 };
2132 const s = S.gimme(@ptrCast(buffer[1..]));
2133 switch (native_endian) {
2134 .big => try expect(s.a == 0x02030405),
2135 .little => try expect(s.a == 0x05040302),
2136 }
2137}
2138
2139test "avoid unused field function body compile error" {
2140 const Case = struct {
2141 const This = @This();
2142
2143 const S = struct {
2144 a: usize = 1,
2145 b: fn () void = This.functionThatDoesNotCompile,
2146 };
2147
2148 const s: S = .{};
2149
2150 fn entry() usize {
2151 return s.a;
2152 }
2153
2154 pub fn functionThatDoesNotCompile() void {
2155 @compileError("told you so");
2156 }
2157 };
2158
2159 try expect(Case.entry() == 1);
2160}
2161
2162test "pass a pointer to a comptime-only struct field to a function" {
2163 const S = struct {
2164 fn checkField(comptime field_ptr: *const type) !void {
2165 try expect(field_ptr.* == u42);
2166 }
2167 };
2168 const s: struct { x: type } = .{ .x = u42 };
2169 try S.checkField(&s.x);
2170}
2171
2172test "overaligned extern struct fields" {
2173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2174 const A = struct {
2175 a: *anyopaque,
2176 b: u64,
2177 c: [1][]u8,
2178 d: ?anyerror,
2179 };
2180
2181 const B = union(enum) {
2182 a: struct {
2183 a: [2]usize,
2184 b: C,
2185 },
2186 b: struct {
2187 a: *anyopaque,
2188 b: []const []u8,
2189 c: C,
2190 },
2191 const C = union {
2192 a: void,
2193 b: *anyopaque,
2194 c: anyerror!usize,
2195 };
2196 };
2197
2198 const D = extern struct {
2199 a: u32,
2200 };
2201
2202 const E = extern struct {
2203 a: u32,
2204 b: [2][@sizeOf(A)]u8 align(@alignOf(A)),
2205 c: [2]u32,
2206 d: [2][@sizeOf(B)]u8 align(@alignOf(B)),
2207
2208 fn cast(e: *@This()) *D {
2209 e.a = 2;
2210 return @ptrCast(e);
2211 }
2212 };
2213
2214 var e: E = undefined;
2215 const d = e.cast();
2216 try expect(d.a == 2);
2217 try expect(std.mem.isAligned(@intFromPtr(&e.b), @alignOf(A)));
2218 try expect(std.mem.isAligned(@intFromPtr(&e.c), @alignOf(u32)));
2219 try expect(std.mem.isAligned(@intFromPtr(&e.d), @alignOf(B)));
2220}
2221
2222test "runtime-known slice of comptime-only struct" {
2223 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2224 const Mixed = struct { index: u32, T: type };
2225
2226 const static = struct {
2227 fn doTheTest(index_offset: usize, s: []const Mixed) !void {
2228 for (s, index_offset..) |*mixed, index| {
2229 try expect(mixed.index == index);
2230 }
2231 }
2232 };
2233
2234 try static.doTheTest(10, &.{
2235 .{ .index = 10, .T = u8 },
2236 .{ .index = 11, .T = noreturn },
2237 .{ .index = 12, .T = *opaque {} },
2238 .{ .index = 13, .T = undefined },
2239 .{ .index = 14, .T = @TypeOf(undefined) },
2240 .{ .index = 15, .T = Mixed },
2241 });
2242}
2243
2244test "struct contains aligned pointer to itself through type decl" {
2245 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2246 const Slab = struct {
2247 const Ptr = *align(64) const @This();
2248 next: Ptr,
2249 };
2250 // We intentionally use `Slab.Ptr` before `Slab`.
2251 var ptr: Slab.Ptr = undefined;
2252 var slab: Slab align(64) = undefined;
2253 ptr = &slab;
2254 slab.next = ptr;
2255
2256 try expect(ptr == &slab);
2257 try expect(slab.next == &slab);
2258 try expect(slab.next.next == &slab);
2259 try expect(slab.next.next.next == &slab);
2260}
2261
2262test "struct contains underaligned field with overaligned pointer to itself" {
2263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2265
2266 const S = struct {
2267 ptr: *align(8) @This() align(1),
2268 };
2269 var val: S align(8) = undefined;
2270 val.ptr = &val;
2271 try expect(val.ptr == &val);
2272 try expect(val.ptr.ptr == &val);
2273 try expect(val.ptr.ptr.ptr == &val);
2274}
2275
2276test "struct contains pointer to function accepting that struct" {
2277 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2278 const S = struct {
2279 const FnPtr = ?*const fn (@This()) void;
2280 fn_ptr: FnPtr,
2281 };
2282 const dummy_fn_ptr: S.FnPtr = @ptrFromInt(0x100000);
2283 const dummy_s: S = .{ .fn_ptr = dummy_fn_ptr };
2284 try expect(dummy_s.fn_ptr == dummy_fn_ptr);
2285 try expect(@TypeOf(dummy_s.fn_ptr.?) == *const fn (S) void);
2286}
2287
2288test "struct queries typeinfo of struct containing pointer back to first struct" {
2289 const static = struct {
2290 const A = struct { b: *B };
2291 const B = struct { a: T: {
2292 _ = @typeInfo(A);
2293 break :T u32;
2294 } };
2295 };
2296 _ = @as(static.A, undefined);
2297}
2298
2299test "pointer to runtime field of struct containing struct containing comptime-only optional" {
2300 const Foo = struct {
2301 padding: struct { a: u8, b: ?comptime_int },
2302 number: u8,
2303 };
2304
2305 const foo: Foo = .{ .padding = undefined, .number = 123 };
2306
2307 var ptr: *const u8 = undefined;
2308 ptr = &foo.number;
2309 try expect(ptr.* == 123);
2310}
2311
2312test "struct field referencing comptime var isn't comptime" {
2313 comptime var v: u8 = 0;
2314 const s = .{ .v = &v };
2315 // field isn't comptime but struct is still comptime-known
2316 comptime assert(!@typeInfo(@TypeOf(s)).@"struct".field_attrs[0].@"comptime");
2317 v = 1;
2318 comptime assert(s.v.* == 1);
2319}