master
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4const assert = std.debug.assert;
5const mem = std.mem;
6const Tag = std.meta.Tag;
7
8const Number = enum { Zero, One, Two, Three, Four };
9
10fn shouldEqual(n: Number, expected: u3) !void {
11 try expect(@intFromEnum(n) == expected);
12}
13
14test "enum to int" {
15 try shouldEqual(Number.Zero, 0);
16 try shouldEqual(Number.One, 1);
17 try shouldEqual(Number.Two, 2);
18 try shouldEqual(Number.Three, 3);
19 try shouldEqual(Number.Four, 4);
20}
21
22fn testEnumFromIntEval(x: i32) !void {
23 try expect(@as(EnumFromIntNumber, @enumFromInt(x)) == EnumFromIntNumber.Three);
24}
25const EnumFromIntNumber = enum { Zero, One, Two, Three, Four };
26
27test "int to enum" {
28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
29
30 try testEnumFromIntEval(3);
31}
32
33const ValueCount1 = enum {
34 I0,
35};
36const ValueCount2 = enum {
37 I0,
38 I1,
39};
40const ValueCount256 = enum {
41 I0,
42 I1,
43 I2,
44 I3,
45 I4,
46 I5,
47 I6,
48 I7,
49 I8,
50 I9,
51 I10,
52 I11,
53 I12,
54 I13,
55 I14,
56 I15,
57 I16,
58 I17,
59 I18,
60 I19,
61 I20,
62 I21,
63 I22,
64 I23,
65 I24,
66 I25,
67 I26,
68 I27,
69 I28,
70 I29,
71 I30,
72 I31,
73 I32,
74 I33,
75 I34,
76 I35,
77 I36,
78 I37,
79 I38,
80 I39,
81 I40,
82 I41,
83 I42,
84 I43,
85 I44,
86 I45,
87 I46,
88 I47,
89 I48,
90 I49,
91 I50,
92 I51,
93 I52,
94 I53,
95 I54,
96 I55,
97 I56,
98 I57,
99 I58,
100 I59,
101 I60,
102 I61,
103 I62,
104 I63,
105 I64,
106 I65,
107 I66,
108 I67,
109 I68,
110 I69,
111 I70,
112 I71,
113 I72,
114 I73,
115 I74,
116 I75,
117 I76,
118 I77,
119 I78,
120 I79,
121 I80,
122 I81,
123 I82,
124 I83,
125 I84,
126 I85,
127 I86,
128 I87,
129 I88,
130 I89,
131 I90,
132 I91,
133 I92,
134 I93,
135 I94,
136 I95,
137 I96,
138 I97,
139 I98,
140 I99,
141 I100,
142 I101,
143 I102,
144 I103,
145 I104,
146 I105,
147 I106,
148 I107,
149 I108,
150 I109,
151 I110,
152 I111,
153 I112,
154 I113,
155 I114,
156 I115,
157 I116,
158 I117,
159 I118,
160 I119,
161 I120,
162 I121,
163 I122,
164 I123,
165 I124,
166 I125,
167 I126,
168 I127,
169 I128,
170 I129,
171 I130,
172 I131,
173 I132,
174 I133,
175 I134,
176 I135,
177 I136,
178 I137,
179 I138,
180 I139,
181 I140,
182 I141,
183 I142,
184 I143,
185 I144,
186 I145,
187 I146,
188 I147,
189 I148,
190 I149,
191 I150,
192 I151,
193 I152,
194 I153,
195 I154,
196 I155,
197 I156,
198 I157,
199 I158,
200 I159,
201 I160,
202 I161,
203 I162,
204 I163,
205 I164,
206 I165,
207 I166,
208 I167,
209 I168,
210 I169,
211 I170,
212 I171,
213 I172,
214 I173,
215 I174,
216 I175,
217 I176,
218 I177,
219 I178,
220 I179,
221 I180,
222 I181,
223 I182,
224 I183,
225 I184,
226 I185,
227 I186,
228 I187,
229 I188,
230 I189,
231 I190,
232 I191,
233 I192,
234 I193,
235 I194,
236 I195,
237 I196,
238 I197,
239 I198,
240 I199,
241 I200,
242 I201,
243 I202,
244 I203,
245 I204,
246 I205,
247 I206,
248 I207,
249 I208,
250 I209,
251 I210,
252 I211,
253 I212,
254 I213,
255 I214,
256 I215,
257 I216,
258 I217,
259 I218,
260 I219,
261 I220,
262 I221,
263 I222,
264 I223,
265 I224,
266 I225,
267 I226,
268 I227,
269 I228,
270 I229,
271 I230,
272 I231,
273 I232,
274 I233,
275 I234,
276 I235,
277 I236,
278 I237,
279 I238,
280 I239,
281 I240,
282 I241,
283 I242,
284 I243,
285 I244,
286 I245,
287 I246,
288 I247,
289 I248,
290 I249,
291 I250,
292 I251,
293 I252,
294 I253,
295 I254,
296 I255,
297};
298const ValueCount257 = enum {
299 I0,
300 I1,
301 I2,
302 I3,
303 I4,
304 I5,
305 I6,
306 I7,
307 I8,
308 I9,
309 I10,
310 I11,
311 I12,
312 I13,
313 I14,
314 I15,
315 I16,
316 I17,
317 I18,
318 I19,
319 I20,
320 I21,
321 I22,
322 I23,
323 I24,
324 I25,
325 I26,
326 I27,
327 I28,
328 I29,
329 I30,
330 I31,
331 I32,
332 I33,
333 I34,
334 I35,
335 I36,
336 I37,
337 I38,
338 I39,
339 I40,
340 I41,
341 I42,
342 I43,
343 I44,
344 I45,
345 I46,
346 I47,
347 I48,
348 I49,
349 I50,
350 I51,
351 I52,
352 I53,
353 I54,
354 I55,
355 I56,
356 I57,
357 I58,
358 I59,
359 I60,
360 I61,
361 I62,
362 I63,
363 I64,
364 I65,
365 I66,
366 I67,
367 I68,
368 I69,
369 I70,
370 I71,
371 I72,
372 I73,
373 I74,
374 I75,
375 I76,
376 I77,
377 I78,
378 I79,
379 I80,
380 I81,
381 I82,
382 I83,
383 I84,
384 I85,
385 I86,
386 I87,
387 I88,
388 I89,
389 I90,
390 I91,
391 I92,
392 I93,
393 I94,
394 I95,
395 I96,
396 I97,
397 I98,
398 I99,
399 I100,
400 I101,
401 I102,
402 I103,
403 I104,
404 I105,
405 I106,
406 I107,
407 I108,
408 I109,
409 I110,
410 I111,
411 I112,
412 I113,
413 I114,
414 I115,
415 I116,
416 I117,
417 I118,
418 I119,
419 I120,
420 I121,
421 I122,
422 I123,
423 I124,
424 I125,
425 I126,
426 I127,
427 I128,
428 I129,
429 I130,
430 I131,
431 I132,
432 I133,
433 I134,
434 I135,
435 I136,
436 I137,
437 I138,
438 I139,
439 I140,
440 I141,
441 I142,
442 I143,
443 I144,
444 I145,
445 I146,
446 I147,
447 I148,
448 I149,
449 I150,
450 I151,
451 I152,
452 I153,
453 I154,
454 I155,
455 I156,
456 I157,
457 I158,
458 I159,
459 I160,
460 I161,
461 I162,
462 I163,
463 I164,
464 I165,
465 I166,
466 I167,
467 I168,
468 I169,
469 I170,
470 I171,
471 I172,
472 I173,
473 I174,
474 I175,
475 I176,
476 I177,
477 I178,
478 I179,
479 I180,
480 I181,
481 I182,
482 I183,
483 I184,
484 I185,
485 I186,
486 I187,
487 I188,
488 I189,
489 I190,
490 I191,
491 I192,
492 I193,
493 I194,
494 I195,
495 I196,
496 I197,
497 I198,
498 I199,
499 I200,
500 I201,
501 I202,
502 I203,
503 I204,
504 I205,
505 I206,
506 I207,
507 I208,
508 I209,
509 I210,
510 I211,
511 I212,
512 I213,
513 I214,
514 I215,
515 I216,
516 I217,
517 I218,
518 I219,
519 I220,
520 I221,
521 I222,
522 I223,
523 I224,
524 I225,
525 I226,
526 I227,
527 I228,
528 I229,
529 I230,
530 I231,
531 I232,
532 I233,
533 I234,
534 I235,
535 I236,
536 I237,
537 I238,
538 I239,
539 I240,
540 I241,
541 I242,
542 I243,
543 I244,
544 I245,
545 I246,
546 I247,
547 I248,
548 I249,
549 I250,
550 I251,
551 I252,
552 I253,
553 I254,
554 I255,
555 I256,
556};
557
558test "enum sizes" {
559 comptime {
560 try expect(@sizeOf(ValueCount1) == 0);
561 try expect(@sizeOf(ValueCount2) == 1);
562 try expect(@sizeOf(ValueCount256) == 1);
563 try expect(@sizeOf(ValueCount257) == 2);
564 }
565}
566
567test "enum literal equality" {
568 const x = .hi;
569 const y = .ok;
570 const z = .hi;
571
572 try expect(x != y);
573 try expect(x == z);
574}
575
576test "enum literal cast to enum" {
577 const Color = enum { Auto, Off, On };
578
579 var color1: Color = .Auto;
580 var color2 = Color.Auto;
581 _ = .{ &color1, &color2 };
582 try expect(color1 == color2);
583}
584
585test "peer type resolution with enum literal" {
586 const Items = enum { one, two };
587
588 try expect(Items.two == .two);
589 try expect(.two == Items.two);
590}
591
592const MultipleChoice = enum(u32) {
593 A = 20,
594 B = 40,
595 C = 60,
596 D = 1000,
597};
598
599fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
600 try expect(@intFromEnum(x) == 60);
601 try expect(1234 == switch (x) {
602 MultipleChoice.A => 1,
603 MultipleChoice.B => 2,
604 MultipleChoice.C => @as(u32, 1234),
605 MultipleChoice.D => 4,
606 });
607}
608
609test "enum with specified tag values" {
610 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
611
612 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
613 try comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
614}
615
616test "non-exhaustive enum" {
617 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
618
619 const S = struct {
620 const E = enum(u8) { a, b, _ };
621
622 fn doTheTest(y: u8) !void {
623 var e: E = .b;
624 try expect(switch (e) {
625 .a => false,
626 .b => true,
627 _ => false,
628 });
629 e = @as(E, @enumFromInt(12));
630 try expect(switch (e) {
631 .a => false,
632 .b => false,
633 _ => true,
634 });
635
636 try expect(switch (e) {
637 .a => false,
638 .b => false,
639 else => true,
640 });
641 e = .b;
642 try expect(switch (e) {
643 .a => false,
644 else => true,
645 });
646
647 try expect(@typeInfo(E).@"enum".fields.len == 2);
648 e = @as(E, @enumFromInt(12));
649 try expect(@intFromEnum(e) == 12);
650 e = @as(E, @enumFromInt(y));
651 try expect(@intFromEnum(e) == 52);
652 try expect(@typeInfo(E).@"enum".is_exhaustive == false);
653 }
654 };
655 try S.doTheTest(52);
656 try comptime S.doTheTest(52);
657}
658
659test "empty non-exhaustive enum" {
660 const S = struct {
661 const E = enum(u8) { _ };
662
663 fn doTheTest(y: u8) !void {
664 var e: E = @enumFromInt(y);
665 _ = &e;
666 try expect(switch (e) {
667 _ => true,
668 });
669 try expect(@intFromEnum(e) == y);
670
671 try expect(@typeInfo(E).@"enum".fields.len == 0);
672 try expect(@typeInfo(E).@"enum".is_exhaustive == false);
673 }
674 };
675 try S.doTheTest(42);
676 try comptime S.doTheTest(42);
677}
678
679test "single field non-exhaustive enum" {
680 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
681
682 const S = struct {
683 const E = enum(u8) { a, _ };
684 fn doTheTest(y: u8) !void {
685 var e: E = .a;
686 try expect(switch (e) {
687 .a => true,
688 _ => false,
689 });
690 e = @as(E, @enumFromInt(12));
691 try expect(switch (e) {
692 .a => false,
693 _ => true,
694 });
695
696 try expect(switch (e) {
697 .a => false,
698 else => true,
699 });
700 e = .a;
701 try expect(switch (e) {
702 .a => true,
703 else => false,
704 });
705
706 try expect(@intFromEnum(@as(E, @enumFromInt(y))) == y);
707 try expect(@typeInfo(E).@"enum".fields.len == 1);
708 try expect(@typeInfo(E).@"enum".is_exhaustive == false);
709 }
710 };
711 try S.doTheTest(23);
712 try comptime S.doTheTest(23);
713}
714
715const EnumWithTagValues = enum(u4) {
716 A = 1 << 0,
717 B = 1 << 1,
718 C = 1 << 2,
719 D = 1 << 3,
720};
721test "enum with tag values don't require parens" {
722 try expect(@intFromEnum(EnumWithTagValues.C) == 0b0100);
723}
724
725const MultipleChoice2 = enum(u32) {
726 Unspecified1,
727 A = 20,
728 Unspecified2,
729 B = 40,
730 Unspecified3,
731 C = 60,
732 Unspecified4,
733 D = 1000,
734 Unspecified5,
735};
736
737test "cast integer literal to enum" {
738 try expect(@as(MultipleChoice2, @enumFromInt(0)) == MultipleChoice2.Unspecified1);
739 try expect(@as(MultipleChoice2, @enumFromInt(40)) == MultipleChoice2.B);
740}
741
742test "enum with specified and unspecified tag values" {
743 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
744
745 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
746 try comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
747}
748
749fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
750 try expect(@intFromEnum(x) == 1000);
751 try expect(1234 == switch (x) {
752 MultipleChoice2.A => 1,
753 MultipleChoice2.B => 2,
754 MultipleChoice2.C => 3,
755 MultipleChoice2.D => @as(u32, 1234),
756 MultipleChoice2.Unspecified1 => 5,
757 MultipleChoice2.Unspecified2 => 6,
758 MultipleChoice2.Unspecified3 => 7,
759 MultipleChoice2.Unspecified4 => 8,
760 MultipleChoice2.Unspecified5 => 9,
761 });
762}
763
764const Small2 = enum(u2) { One, Two };
765const Small = enum(u2) { One, Two, Three, Four };
766
767test "set enum tag type" {
768 {
769 var x = Small.One;
770 x = Small.Two;
771 comptime assert(Tag(Small) == u2);
772 }
773 {
774 var x = Small2.One;
775 x = Small2.Two;
776 comptime assert(Tag(Small2) == u2);
777 }
778}
779
780test "casting enum to its tag type" {
781 try testCastEnumTag(Small2.Two);
782 try comptime testCastEnumTag(Small2.Two);
783}
784
785fn testCastEnumTag(value: Small2) !void {
786 try expect(@intFromEnum(value) == 1);
787}
788
789test "enum with 1 field but explicit tag type should still have the tag type" {
790 const Enum = enum(u8) {
791 B = 2,
792 };
793 comptime assert(@sizeOf(Enum) == @sizeOf(u8));
794}
795
796test "signed integer as enum tag" {
797 const SignedEnum = enum(i2) {
798 A0 = -1,
799 A1 = 0,
800 A2 = 1,
801 };
802
803 try expect(@intFromEnum(SignedEnum.A0) == -1);
804 try expect(@intFromEnum(SignedEnum.A1) == 0);
805 try expect(@intFromEnum(SignedEnum.A2) == 1);
806}
807
808test "enum with one member and custom tag type" {
809 const E = enum(u2) {
810 One,
811 };
812 try expect(@intFromEnum(E.One) == 0);
813 const E2 = enum(u2) {
814 One = 2,
815 };
816 try expect(@intFromEnum(E2.One) == 2);
817}
818
819test "enum with one member and u1 tag type @intFromEnum" {
820 const Enum = enum(u1) {
821 Test,
822 };
823 try expect(@intFromEnum(Enum.Test) == 0);
824}
825
826test "enum with comptime_int tag type" {
827 const Enum = enum(comptime_int) {
828 One = 3,
829 Two = 2,
830 Three = 1,
831 };
832 comptime assert(Tag(Enum) == comptime_int);
833}
834
835test "enum with one member default to u0 tag type" {
836 const E0 = enum { X };
837 comptime assert(Tag(E0) == u0);
838}
839
840const EnumWithOneMember = enum { Eof };
841
842fn doALoopThing(id: EnumWithOneMember) void {
843 while (true) {
844 if (id == EnumWithOneMember.Eof) {
845 break;
846 }
847 @compileError("above if condition should be comptime");
848 }
849}
850
851test "comparison operator on enum with one member is comptime-known" {
852 doALoopThing(EnumWithOneMember.Eof);
853}
854
855const State = enum { Start };
856test "switch on enum with one member is comptime-known" {
857 var state = State.Start;
858 _ = &state;
859 switch (state) {
860 State.Start => return,
861 }
862 @compileError("analysis should not reach here");
863}
864
865test "method call on an enum" {
866 const S = struct {
867 const E = enum {
868 one,
869 two,
870
871 fn method(self: *E) bool {
872 return self.* == .two;
873 }
874
875 fn generic_method(self: *E, foo: anytype) bool {
876 return self.* == .two and foo == bool;
877 }
878 };
879 fn doTheTest() !void {
880 var e = E.two;
881 try expect(e.method());
882 try expect(e.generic_method(bool));
883 }
884 };
885 try S.doTheTest();
886 try comptime S.doTheTest();
887}
888
889test "enum value allocation" {
890 const LargeEnum = enum(u32) {
891 A0 = 0x80000000,
892 A1,
893 A2,
894 };
895
896 try expect(@intFromEnum(LargeEnum.A0) == 0x80000000);
897 try expect(@intFromEnum(LargeEnum.A1) == 0x80000001);
898 try expect(@intFromEnum(LargeEnum.A2) == 0x80000002);
899}
900
901test "enum literal casting to tagged union" {
902 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
903 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
904
905 const Arch = union(enum) {
906 x86_64,
907 arm: Arm32,
908
909 const Arm32 = enum {
910 v8_5a,
911 v8_4a,
912 };
913 };
914
915 var t = true;
916 var x: Arch = .x86_64;
917 _ = .{ &t, &x };
918 const y = if (t) x else .x86_64;
919 switch (y) {
920 .x86_64 => {},
921 else => @panic("fail"),
922 }
923}
924
925const Bar = enum { A, B, C, D };
926
927test "enum literal casting to error union with payload enum" {
928 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
929
930 var bar: error{B}!Bar = undefined;
931 bar = .B; // should never cast to the error set
932
933 try expect((try bar) == Bar.B);
934}
935
936test "constant enum initialization with differing sizes" {
937 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
938 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
939 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
940 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
941
942 try test3_1(test3_foo);
943 try test3_2(test3_bar);
944}
945const Test3Foo = union(enum) {
946 One: void,
947 Two: f32,
948 Three: Test3Point,
949};
950const Test3Point = struct {
951 x: i32,
952 y: i32,
953};
954const test3_foo = Test3Foo{
955 .Three = Test3Point{
956 .x = 3,
957 .y = 4,
958 },
959};
960const test3_bar = Test3Foo{ .Two = 13 };
961fn test3_1(f: Test3Foo) !void {
962 switch (f) {
963 Test3Foo.Three => |pt| {
964 try expect(pt.x == 3);
965 try expect(pt.y == 4);
966 },
967 else => unreachable,
968 }
969}
970fn test3_2(f: Test3Foo) !void {
971 switch (f) {
972 Test3Foo.Two => |x| {
973 try expect(x == 13);
974 },
975 else => unreachable,
976 }
977}
978
979test "@tagName" {
980 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
981 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
982 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
983 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
984 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
985
986 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
987 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
988}
989
990fn testEnumTagNameBare(n: anytype) []const u8 {
991 return @tagName(n);
992}
993
994const BareNumber = enum { One, Two, Three };
995
996test "@tagName non-exhaustive enum" {
997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
999 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1000 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1001 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1002
1003 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
1004 comptime assert(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
1005}
1006const NonExhaustive = enum(u8) { A, B, _ };
1007
1008test "@tagName is null-terminated" {
1009 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1011 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1012 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1013 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1014
1015 const S = struct {
1016 fn doTheTest(n: BareNumber) !void {
1017 try expect(@tagName(n)[3] == 0);
1018 }
1019 };
1020 try S.doTheTest(.Two);
1021 try comptime S.doTheTest(.Two);
1022}
1023
1024test "tag name with assigned enum values" {
1025 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1026 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1027 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1028 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1029 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1030
1031 const LocalFoo = enum(u8) {
1032 A = 1,
1033 B = 0,
1034 };
1035 var b = LocalFoo.B;
1036 _ = &b;
1037 try expect(mem.eql(u8, @tagName(b), "B"));
1038}
1039
1040test "@tagName on enum literals" {
1041 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1042 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1043
1044 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1045 comptime assert(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1046}
1047
1048test "tag name with signed enum values" {
1049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1050 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1051 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1052 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1053 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1054
1055 const LocalFoo = enum(isize) {
1056 alfa = 62,
1057 bravo = 63,
1058 charlie = 64,
1059 delta = 65,
1060 };
1061 var b = LocalFoo.bravo;
1062 _ = &b;
1063 try expect(mem.eql(u8, @tagName(b), "bravo"));
1064}
1065
1066test "tag name with large enum values" {
1067 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1068 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1069
1070 const Kdf = enum(u128) {
1071 aes_kdf = 0xea4f8ac1080d74bf60448a629af3d9c9,
1072 argon2d = 0x0c0ae303a4a9f7914b44298cdf6d63ef,
1073 argon2id = 0xe6a1f0c63efc3db27347db56198b299e,
1074 };
1075 var kdf: Kdf = .aes_kdf;
1076 try expect(mem.eql(u8, @tagName(kdf), "aes_kdf"));
1077 var argon2d_value: u128 = undefined;
1078 argon2d_value = @intFromEnum(Kdf.argon2d);
1079 kdf = @enumFromInt(argon2d_value);
1080 try expect(mem.eql(u8, @tagName(kdf), "argon2d"));
1081 kdf = .argon2id;
1082 try expect(mem.eql(u8, @tagName(kdf), "argon2id"));
1083}
1084
1085test "@tagName in callconv(.c) function" {
1086 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1088 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1089 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1090 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1091
1092 try expect(mem.orderZ(u8, testEnumTagNameCallconvC(), "Two") == .eq);
1093 comptime assert(mem.orderZ(u8, testEnumTagNameCallconvC(), "Two") == .eq);
1094}
1095
1096fn testEnumTagNameCallconvC() callconv(.c) [*:0]const u8 {
1097 var e: BareNumber = .Two;
1098 _ = &e;
1099 return @tagName(e);
1100}
1101
1102test "enum literal casting to optional" {
1103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1105
1106 var bar: ?Bar = undefined;
1107 bar = .B;
1108
1109 try expect(bar.? == Bar.B);
1110}
1111
1112const A = enum(u3) { One, Two, Three, Four, One2, Two2, Three2, Four2 };
1113const B = enum(u3) { One3, Two3, Three3, Four3, One23, Two23, Three23, Four23 };
1114const C = enum(u2) { One4, Two4, Three4, Four4 };
1115
1116const BitFieldOfEnums = packed struct {
1117 a: A,
1118 b: B,
1119 c: C,
1120};
1121
1122const bit_field_1 = BitFieldOfEnums{
1123 .a = A.Two,
1124 .b = B.Three3,
1125 .c = C.Four4,
1126};
1127
1128test "bit field access with enum fields" {
1129 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1132 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1133 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1134
1135 var data = bit_field_1;
1136 try expect(getA(&data) == A.Two);
1137 try expect(getB(&data) == B.Three3);
1138 try expect(getC(&data) == C.Four4);
1139 comptime assert(@sizeOf(BitFieldOfEnums) == 1);
1140
1141 data.b = B.Four3;
1142 try expect(data.b == B.Four3);
1143
1144 data.a = A.Three;
1145 try expect(data.a == A.Three);
1146 try expect(data.b == B.Four3);
1147}
1148
1149fn getA(data: *const BitFieldOfEnums) A {
1150 return data.a;
1151}
1152
1153fn getB(data: *const BitFieldOfEnums) B {
1154 return data.b;
1155}
1156
1157fn getC(data: *const BitFieldOfEnums) C {
1158 return data.c;
1159}
1160
1161test "enum literal in array literal" {
1162 const Items = enum { one, two };
1163 const array = [_]Items{ .one, .two };
1164
1165 try expect(array[0] == .one);
1166 try expect(array[1] == .two);
1167}
1168
1169test "tag name functions are unique" {
1170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1174 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1175
1176 {
1177 const E = enum { a, b };
1178 var b = E.a;
1179 var a = @tagName(b);
1180 _ = .{ &a, &b };
1181 }
1182 {
1183 const E = enum { a, b, c, d, e, f };
1184 var b = E.a;
1185 var a = @tagName(b);
1186 _ = .{ &a, &b };
1187 }
1188}
1189
1190test "size of enum with only one tag which has explicit integer tag type" {
1191 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1192
1193 const E = enum(u8) { nope = 10 };
1194 const S0 = struct { e: E };
1195 const S1 = extern struct { e: E };
1196 //const U = union(E) { nope: void };
1197 comptime assert(@sizeOf(E) == 1);
1198 comptime assert(@sizeOf(S0) == 1);
1199 comptime assert(@sizeOf(S1) == 1);
1200 //comptime assert(@sizeOf(U) == 1);
1201
1202 var s1: S1 = undefined;
1203 s1.e = .nope;
1204 try expect(s1.e == .nope);
1205 const ptr = @as(*u8, @ptrCast(&s1));
1206 try expect(ptr.* == 10);
1207
1208 var s0: S0 = undefined;
1209 s0.e = .nope;
1210 try expect(s0.e == .nope);
1211}
1212
1213test "switch on an extern enum with negative value" {
1214 const Foo = enum(c_int) {
1215 Bar = -1,
1216 };
1217
1218 const v = Foo.Bar;
1219
1220 switch (v) {
1221 Foo.Bar => return,
1222 }
1223}
1224
1225test "Non-exhaustive enum with nonstandard int size behaves correctly" {
1226 const E = enum(u15) { _ };
1227 try expect(@sizeOf(E) == @sizeOf(u15));
1228}
1229
1230test "runtime int to enum with one possible value" {
1231 const E = enum { one };
1232 var runtime: usize = 0;
1233 _ = &runtime;
1234 if (@as(E, @enumFromInt(runtime)) != .one) {
1235 @compileError("test failed");
1236 }
1237}
1238
1239test "enum tag from a local variable" {
1240 const S = struct {
1241 fn Int(comptime Inner: type) type {
1242 return enum(Inner) { _ };
1243 }
1244 };
1245 const i = @as(S.Int(u32), @enumFromInt(0));
1246 try std.testing.expect(@intFromEnum(i) == 0);
1247}
1248
1249test "auto-numbered enum with signed tag type" {
1250 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1251
1252 const E = enum(i32) { a, b };
1253
1254 try std.testing.expectEqual(@as(i32, 0), @intFromEnum(E.a));
1255 try std.testing.expectEqual(@as(i32, 1), @intFromEnum(E.b));
1256 try std.testing.expectEqual(E.a, @as(E, @enumFromInt(0)));
1257 try std.testing.expectEqual(E.b, @as(E, @enumFromInt(1)));
1258 try std.testing.expectEqual(E.a, @as(E, @enumFromInt(@as(i32, 0))));
1259 try std.testing.expectEqual(E.b, @as(E, @enumFromInt(@as(i32, 1))));
1260 try std.testing.expectEqual(E.a, @as(E, @enumFromInt(@as(u32, 0))));
1261 try std.testing.expectEqual(E.b, @as(E, @enumFromInt(@as(u32, 1))));
1262 try std.testing.expectEqualStrings("a", @tagName(E.a));
1263 try std.testing.expectEqualStrings("b", @tagName(E.b));
1264}
1265
1266test "lazy initialized field" {
1267 try std.testing.expectEqual(@as(u8, @alignOf(struct {})), getLazyInitialized(.a));
1268}
1269
1270fn getLazyInitialized(param: enum(u8) {
1271 a = @bitCast(packed struct(u8) { a: u8 }{ .a = @alignOf(struct {}) }),
1272}) u8 {
1273 return @intFromEnum(param);
1274}
1275
1276test "Non-exhaustive enum backed by comptime_int" {
1277 const E = enum(comptime_int) { a, b, c, _ };
1278 comptime var e: E = .a;
1279 e = @as(E, @enumFromInt(378089457309184723749));
1280 try expect(@intFromEnum(e) == 378089457309184723749);
1281}
1282
1283test "matching captures causes enum equivalence" {
1284 const S = struct {
1285 fn Nonexhaustive(comptime I: type) type {
1286 const UTag = @Int(.unsigned, @typeInfo(I).int.bits);
1287 return enum(UTag) { _ };
1288 }
1289 };
1290
1291 comptime assert(S.Nonexhaustive(u8) == S.Nonexhaustive(i8));
1292 comptime assert(S.Nonexhaustive(u16) == S.Nonexhaustive(i16));
1293 comptime assert(S.Nonexhaustive(u8) != S.Nonexhaustive(u16));
1294
1295 const a: S.Nonexhaustive(u8) = @enumFromInt(123);
1296 const b: S.Nonexhaustive(i8) = @enumFromInt(123);
1297 comptime assert(@TypeOf(a) == @TypeOf(b));
1298 try expect(@intFromEnum(a) == @intFromEnum(b));
1299}
1300
1301test "large enum field values" {
1302 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1304
1305 {
1306 const E = enum(u64) { min = std.math.minInt(u64), max = std.math.maxInt(u64) };
1307 var e: E = .min;
1308 try expect(e == .min);
1309 try expect(@intFromEnum(e) == std.math.minInt(u64));
1310 e = .max;
1311 try expect(e == .max);
1312 try expect(@intFromEnum(e) == std.math.maxInt(u64));
1313 }
1314 {
1315 const E = enum(i64) { min = std.math.minInt(i64), max = std.math.maxInt(i64) };
1316 var e: E = .min;
1317 try expect(e == .min);
1318 try expect(@intFromEnum(e) == std.math.minInt(i64));
1319 e = .max;
1320 try expect(e == .max);
1321 try expect(@intFromEnum(e) == std.math.maxInt(i64));
1322 }
1323 {
1324 const E = enum(u128) { min = std.math.minInt(u128), max = std.math.maxInt(u128) };
1325 var e: E = .min;
1326 try expect(e == .min);
1327 try expect(@intFromEnum(e) == std.math.minInt(u128));
1328 e = .max;
1329 try expect(e == .max);
1330 try expect(@intFromEnum(e) == std.math.maxInt(u128));
1331 }
1332 {
1333 const E = enum(i128) { min = std.math.minInt(i128), max = std.math.maxInt(i128) };
1334 var e: E = .min;
1335 try expect(e == .min);
1336 try expect(@intFromEnum(e) == std.math.minInt(i128));
1337 e = .max;
1338 try expect(e == .max);
1339 try expect(@intFromEnum(e) == std.math.maxInt(i128));
1340 }
1341}
1342
1343test "comptime @enumFromInt with signed arithmetic" {
1344 const E = enum(i8) { foo = -1, bar = 0 };
1345 const x: E = @enumFromInt(@as(i8, -1) * 0);
1346 comptime assert(x == .bar);
1347 comptime assert(@intFromEnum(x) == 0);
1348}