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}