zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 4c0b4a88 (25693B) - Raw


      1 const builtin = @import("builtin");
      2 const std = @import("std");
      3 const assert = std.debug.assert;
      4 const expect = std.testing.expect;
      5 const expectError = std.testing.expectError;
      6 const expectEqual = std.testing.expectEqual;
      7 
      8 test "switch with numbers" {
      9     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     10 
     11     try testSwitchWithNumbers(13);
     12 }
     13 
     14 fn testSwitchWithNumbers(x: u32) !void {
     15     const result = switch (x) {
     16         1, 2, 3, 4...8 => false,
     17         13 => true,
     18         else => false,
     19     };
     20     try expect(result);
     21 }
     22 
     23 test "switch with all ranges" {
     24     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     25 
     26     try expect(testSwitchWithAllRanges(50, 3) == 1);
     27     try expect(testSwitchWithAllRanges(101, 0) == 2);
     28     try expect(testSwitchWithAllRanges(300, 5) == 3);
     29     try expect(testSwitchWithAllRanges(301, 6) == 6);
     30 }
     31 
     32 fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
     33     return switch (x) {
     34         0...100 => 1,
     35         101...200 => 2,
     36         201...300 => 3,
     37         else => y,
     38     };
     39 }
     40 
     41 test "implicit comptime switch" {
     42     const x = 3 + 4;
     43     const result = switch (x) {
     44         3 => 10,
     45         4 => 11,
     46         5, 6 => 12,
     47         7, 8 => 13,
     48         else => 14,
     49     };
     50 
     51     comptime {
     52         try expect(result + 1 == 14);
     53     }
     54 }
     55 
     56 test "switch on enum" {
     57     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     58 
     59     const fruit = Fruit.Orange;
     60     try expect(nonConstSwitchOnEnum(fruit));
     61 }
     62 const Fruit = enum {
     63     Apple,
     64     Orange,
     65     Banana,
     66 };
     67 fn nonConstSwitchOnEnum(fruit: Fruit) bool {
     68     return switch (fruit) {
     69         Fruit.Apple => false,
     70         Fruit.Orange => true,
     71         Fruit.Banana => false,
     72     };
     73 }
     74 
     75 test "switch statement" {
     76     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     77 
     78     try nonConstSwitch(SwitchStatementFoo.C);
     79 }
     80 fn nonConstSwitch(foo: SwitchStatementFoo) !void {
     81     const val = switch (foo) {
     82         SwitchStatementFoo.A => @as(i32, 1),
     83         SwitchStatementFoo.B => 2,
     84         SwitchStatementFoo.C => 3,
     85         SwitchStatementFoo.D => 4,
     86     };
     87     try expect(val == 3);
     88 }
     89 const SwitchStatementFoo = enum { A, B, C, D };
     90 
     91 test "switch with multiple expressions" {
     92     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     93 
     94     const x = switch (returnsFive()) {
     95         1, 2, 3 => 1,
     96         4, 5, 6 => 2,
     97         else => @as(i32, 3),
     98     };
     99     try expect(x == 2);
    100 }
    101 fn returnsFive() i32 {
    102     return 5;
    103 }
    104 
    105 test "switch on type" {
    106     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    107 
    108     try expect(trueIfBoolFalseOtherwise(bool));
    109     try expect(!trueIfBoolFalseOtherwise(i32));
    110 }
    111 
    112 fn trueIfBoolFalseOtherwise(comptime T: type) bool {
    113     return switch (T) {
    114         bool => true,
    115         else => false,
    116     };
    117 }
    118 
    119 test "switching on booleans" {
    120     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    121 
    122     try testSwitchOnBools();
    123     try comptime testSwitchOnBools();
    124 }
    125 
    126 fn testSwitchOnBools() !void {
    127     try expect(testSwitchOnBoolsTrueAndFalse(true) == false);
    128     try expect(testSwitchOnBoolsTrueAndFalse(false) == true);
    129 
    130     try expect(testSwitchOnBoolsTrueWithElse(true) == false);
    131     try expect(testSwitchOnBoolsTrueWithElse(false) == true);
    132 
    133     try expect(testSwitchOnBoolsFalseWithElse(true) == false);
    134     try expect(testSwitchOnBoolsFalseWithElse(false) == true);
    135 }
    136 
    137 fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
    138     return switch (x) {
    139         true => false,
    140         false => true,
    141     };
    142 }
    143 
    144 fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
    145     return switch (x) {
    146         true => false,
    147         else => true,
    148     };
    149 }
    150 
    151 fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
    152     return switch (x) {
    153         false => true,
    154         else => false,
    155     };
    156 }
    157 
    158 test "u0" {
    159     var val: u0 = 0;
    160     _ = &val;
    161     switch (val) {
    162         0 => try expect(val == 0),
    163     }
    164 }
    165 
    166 test "undefined.u0" {
    167     var val: u0 = undefined;
    168     _ = &val;
    169     switch (val) {
    170         0 => try expect(val == 0),
    171     }
    172 }
    173 
    174 test "switch with disjoint range" {
    175     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    176 
    177     var q: u8 = 0;
    178     _ = &q;
    179     switch (q) {
    180         0...125 => {},
    181         127...255 => {},
    182         126...126 => {},
    183     }
    184 }
    185 
    186 test "switch variable for range and multiple prongs" {
    187     const S = struct {
    188         fn doTheTest() !void {
    189             try doTheSwitch(16);
    190             try doTheSwitch(42);
    191         }
    192         fn doTheSwitch(q: u8) !void {
    193             switch (q) {
    194                 0...40 => |x| try expect(x == 16),
    195                 41, 42, 43 => |x| try expect(x == 42),
    196                 else => try expect(false),
    197             }
    198         }
    199     };
    200     try S.doTheTest();
    201     try comptime S.doTheTest();
    202 }
    203 
    204 var state: u32 = 0;
    205 fn poll() void {
    206     switch (state) {
    207         0 => {
    208             state = 1;
    209         },
    210         else => {
    211             state += 1;
    212         },
    213     }
    214 }
    215 
    216 test "switch on global mutable var isn't constant-folded" {
    217     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    218 
    219     while (state < 2) {
    220         poll();
    221     }
    222 }
    223 
    224 const SwitchProngWithVarEnum = union(enum) {
    225     One: i32,
    226     Two: f32,
    227     Meh: void,
    228 };
    229 
    230 test "switch prong with variable" {
    231     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    232     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    233     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    234     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    235 
    236     try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
    237     try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
    238     try switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
    239 }
    240 fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
    241     switch (a) {
    242         SwitchProngWithVarEnum.One => |x| {
    243             try expect(x == 13);
    244         },
    245         SwitchProngWithVarEnum.Two => |x| {
    246             try expect(x == 13.0);
    247         },
    248         SwitchProngWithVarEnum.Meh => |x| {
    249             const v: void = x;
    250             _ = v;
    251         },
    252     }
    253 }
    254 
    255 test "switch on enum using pointer capture" {
    256     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    257     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    258     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    259 
    260     try testSwitchEnumPtrCapture();
    261     try comptime testSwitchEnumPtrCapture();
    262 }
    263 
    264 fn testSwitchEnumPtrCapture() !void {
    265     var value = SwitchProngWithVarEnum{ .One = 1234 };
    266     switch (value) {
    267         SwitchProngWithVarEnum.One => |*x| x.* += 1,
    268         else => unreachable,
    269     }
    270     switch (value) {
    271         SwitchProngWithVarEnum.One => |x| try expect(x == 1235),
    272         else => unreachable,
    273     }
    274 }
    275 
    276 test "switch handles all cases of number" {
    277     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    278 
    279     try testSwitchHandleAllCases();
    280     try comptime testSwitchHandleAllCases();
    281 }
    282 
    283 fn testSwitchHandleAllCases() !void {
    284     try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
    285     try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
    286     try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
    287     try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
    288 
    289     try expect(testSwitchHandleAllCasesRange(100) == 0);
    290     try expect(testSwitchHandleAllCasesRange(200) == 1);
    291     try expect(testSwitchHandleAllCasesRange(201) == 2);
    292     try expect(testSwitchHandleAllCasesRange(202) == 4);
    293     try expect(testSwitchHandleAllCasesRange(230) == 3);
    294 }
    295 
    296 fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
    297     return switch (x) {
    298         0 => @as(u2, 3),
    299         1 => 2,
    300         2 => 1,
    301         3 => 0,
    302     };
    303 }
    304 
    305 fn testSwitchHandleAllCasesRange(x: u8) u8 {
    306     return switch (x) {
    307         0...100 => @as(u8, 0),
    308         101...200 => 1,
    309         201, 203 => 2,
    310         202 => 4,
    311         204...255 => 3,
    312     };
    313 }
    314 
    315 test "switch on union with some prongs capturing" {
    316     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    317     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    318     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    319     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    320 
    321     const X = union(enum) {
    322         a,
    323         b: i32,
    324     };
    325 
    326     var x: X = X{ .b = 10 };
    327     _ = &x;
    328     const y: i32 = switch (x) {
    329         .a => unreachable,
    330         .b => |b| b + 1,
    331     };
    332     try expect(y == 11);
    333 }
    334 
    335 const Number = union(enum) {
    336     One: u64,
    337     Two: u8,
    338     Three: f32,
    339 };
    340 
    341 const number = Number{ .Three = 1.23 };
    342 
    343 fn returnsFalse() bool {
    344     switch (number) {
    345         Number.One => |x| return x > 1234,
    346         Number.Two => |x| return x == 'a',
    347         Number.Three => |x| return x > 12.34,
    348     }
    349 }
    350 test "switch on const enum with var" {
    351     try expect(!returnsFalse());
    352 }
    353 
    354 test "anon enum literal used in switch on union enum" {
    355     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    356     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    357 
    358     const Foo = union(enum) {
    359         a: i32,
    360     };
    361 
    362     var foo = Foo{ .a = 1234 };
    363     _ = &foo;
    364     switch (foo) {
    365         .a => |x| {
    366             try expect(x == 1234);
    367         },
    368     }
    369 }
    370 
    371 test "switch all prongs unreachable" {
    372     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    373 
    374     try testAllProngsUnreachable();
    375     try comptime testAllProngsUnreachable();
    376 }
    377 
    378 fn testAllProngsUnreachable() !void {
    379     try expect(switchWithUnreachable(1) == 2);
    380     try expect(switchWithUnreachable(2) == 10);
    381 }
    382 
    383 fn switchWithUnreachable(x: i32) i32 {
    384     while (true) {
    385         switch (x) {
    386             1 => return 2,
    387             2 => break,
    388             else => continue,
    389         }
    390     }
    391     return 10;
    392 }
    393 
    394 test "capture value of switch with all unreachable prongs" {
    395     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    396 
    397     const x = return_a_number() catch |err| switch (err) {
    398         else => unreachable,
    399     };
    400     try expect(x == 1);
    401 }
    402 
    403 fn return_a_number() anyerror!i32 {
    404     return 1;
    405 }
    406 
    407 test "switch on integer with else capturing expr" {
    408     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    409 
    410     const S = struct {
    411         fn doTheTest() !void {
    412             var x: i32 = 5;
    413             _ = &x;
    414             switch (x + 10) {
    415                 14 => return error.TestFailed,
    416                 16 => return error.TestFailed,
    417                 else => |e| try expect(e == 15),
    418             }
    419         }
    420     };
    421     try S.doTheTest();
    422     try comptime S.doTheTest();
    423 }
    424 
    425 test "else prong of switch on error set excludes other cases" {
    426     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    427     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    428     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    429     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    430 
    431     const S = struct {
    432         fn doTheTest() !void {
    433             try expectError(error.C, bar());
    434         }
    435         const E = error{
    436             A,
    437             B,
    438         } || E2;
    439 
    440         const E2 = error{
    441             C,
    442             D,
    443         };
    444 
    445         fn foo() E!void {
    446             return error.C;
    447         }
    448 
    449         fn bar() E2!void {
    450             foo() catch |err| switch (err) {
    451                 error.A, error.B => {},
    452                 else => |e| return e,
    453             };
    454         }
    455     };
    456     try S.doTheTest();
    457     try comptime S.doTheTest();
    458 }
    459 
    460 test "switch prongs with error set cases make a new error set type for capture value" {
    461     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    462     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    463     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    464     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    465 
    466     const S = struct {
    467         fn doTheTest() !void {
    468             try expectError(error.B, bar());
    469         }
    470         const E = E1 || E2;
    471 
    472         const E1 = error{
    473             A,
    474             B,
    475         };
    476 
    477         const E2 = error{
    478             C,
    479             D,
    480         };
    481 
    482         fn foo() E!void {
    483             return error.B;
    484         }
    485 
    486         fn bar() E1!void {
    487             foo() catch |err| switch (err) {
    488                 error.A, error.B => |e| return e,
    489                 else => {},
    490             };
    491         }
    492     };
    493     try S.doTheTest();
    494     try comptime S.doTheTest();
    495 }
    496 
    497 test "return result loc and then switch with range implicit casted to error union" {
    498     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    499 
    500     const S = struct {
    501         fn doTheTest() !void {
    502             try expect((func(0xb) catch unreachable) == 0xb);
    503         }
    504         fn func(d: u8) anyerror!u8 {
    505             return switch (d) {
    506                 0xa...0xf => d,
    507                 else => unreachable,
    508             };
    509         }
    510     };
    511     try S.doTheTest();
    512     try comptime S.doTheTest();
    513 }
    514 
    515 test "switch with null and T peer types and inferred result location type" {
    516     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    517     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    518     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    519 
    520     const S = struct {
    521         fn doTheTest(c: u8) !void {
    522             if (switch (c) {
    523                 0 => true,
    524                 else => null,
    525             }) |v| {
    526                 _ = v;
    527                 return error.TestFailed;
    528             }
    529         }
    530     };
    531     try S.doTheTest(1);
    532     try comptime S.doTheTest(1);
    533 }
    534 
    535 test "switch prongs with cases with identical payload types" {
    536     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    537     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    538     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    539     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    540 
    541     const Union = union(enum) {
    542         A: usize,
    543         B: isize,
    544         C: usize,
    545     };
    546     const S = struct {
    547         fn doTheTest() !void {
    548             try doTheSwitch1(Union{ .A = 8 });
    549             try doTheSwitch2(Union{ .B = -8 });
    550         }
    551         fn doTheSwitch1(u: Union) !void {
    552             switch (u) {
    553                 .A, .C => |e| {
    554                     comptime assert(@TypeOf(e) == usize);
    555                     try expect(e == 8);
    556                 },
    557                 .B => |e| {
    558                     _ = e;
    559                     return error.TestFailed;
    560                 },
    561             }
    562         }
    563         fn doTheSwitch2(u: Union) !void {
    564             switch (u) {
    565                 .A, .C => |e| {
    566                     _ = e;
    567                     return error.TestFailed;
    568                 },
    569                 .B => |e| {
    570                     comptime assert(@TypeOf(e) == isize);
    571                     try expect(e == -8);
    572                 },
    573             }
    574         }
    575     };
    576     try S.doTheTest();
    577     try comptime S.doTheTest();
    578 }
    579 
    580 test "switch prong pointer capture alignment" {
    581     const U = union(enum) {
    582         a: u8 align(8),
    583         b: u8 align(4),
    584         c: u8,
    585     };
    586 
    587     const S = struct {
    588         fn doTheTest() !void {
    589             const u = U{ .a = 1 };
    590             switch (u) {
    591                 .a => |*a| comptime assert(@TypeOf(a) == *align(8) const u8),
    592                 .b, .c => |*p| {
    593                     _ = p;
    594                     return error.TestFailed;
    595                 },
    596             }
    597 
    598             switch (u) {
    599                 .a, .b => |*p| comptime assert(@TypeOf(p) == *align(4) const u8),
    600                 .c => |*p| {
    601                     _ = p;
    602                     return error.TestFailed;
    603                 },
    604             }
    605 
    606             switch (u) {
    607                 .a, .c => |*p| comptime assert(@TypeOf(p) == *const u8),
    608                 .b => |*p| {
    609                     _ = p;
    610                     return error.TestFailed;
    611                 },
    612             }
    613         }
    614 
    615         fn doTheTest2() !void {
    616             const un1 = U{ .b = 1 };
    617             switch (un1) {
    618                 .b => |*b| comptime assert(@TypeOf(b) == *align(4) const u8),
    619                 .a, .c => |*p| {
    620                     _ = p;
    621                     return error.TestFailed;
    622                 },
    623             }
    624 
    625             const un2 = U{ .c = 1 };
    626             switch (un2) {
    627                 .c => |*c| comptime assert(@TypeOf(c) == *const u8),
    628                 .a, .b => |*p| {
    629                     _ = p;
    630                     return error.TestFailed;
    631                 },
    632             }
    633         }
    634     };
    635 
    636     try S.doTheTest();
    637     try comptime S.doTheTest();
    638 
    639     try S.doTheTest2();
    640     try comptime S.doTheTest2();
    641 }
    642 
    643 test "switch on pointer type" {
    644     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    645     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    646 
    647     const S = struct {
    648         const X = struct {
    649             field: u32,
    650         };
    651 
    652         const P1 = @as(*X, @ptrFromInt(0x400));
    653         const P2 = @as(*X, @ptrFromInt(0x800));
    654         const P3 = @as(*X, @ptrFromInt(0xC00));
    655 
    656         fn doTheTest(arg: *X) i32 {
    657             switch (arg) {
    658                 P1 => return 1,
    659                 P2 => return 2,
    660                 else => return 3,
    661             }
    662         }
    663     };
    664 
    665     try expect(1 == S.doTheTest(S.P1));
    666     try expect(2 == S.doTheTest(S.P2));
    667     try expect(3 == S.doTheTest(S.P3));
    668     comptime assert(1 == S.doTheTest(S.P1));
    669     comptime assert(2 == S.doTheTest(S.P2));
    670     comptime assert(3 == S.doTheTest(S.P3));
    671 }
    672 
    673 test "switch on error set with single else" {
    674     const S = struct {
    675         fn doTheTest() !void {
    676             var some: error{Foo} = error.Foo;
    677             _ = &some;
    678             try expect(switch (some) {
    679                 else => blk: {
    680                     break :blk true;
    681                 },
    682             });
    683         }
    684     };
    685 
    686     try S.doTheTest();
    687     try comptime S.doTheTest();
    688 }
    689 
    690 test "switch capture copies its payload" {
    691     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    692     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    693     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    694 
    695     const S = struct {
    696         fn doTheTest() !void {
    697             var tmp: union(enum) {
    698                 A: u8,
    699                 B: u32,
    700             } = .{ .A = 42 };
    701             switch (tmp) {
    702                 .A => |value| {
    703                     // Modify the original union
    704                     tmp = .{ .B = 0x10101010 };
    705                     try expectEqual(@as(u8, 42), value);
    706                 },
    707                 else => unreachable,
    708             }
    709         }
    710     };
    711     try S.doTheTest();
    712     try comptime S.doTheTest();
    713 }
    714 
    715 test "capture of integer forwards the switch condition directly" {
    716     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    717 
    718     const S = struct {
    719         fn foo(x: u8) !void {
    720             switch (x) {
    721                 40...45 => |capture| {
    722                     try expect(capture == 42);
    723                 },
    724                 else => |capture| {
    725                     try expect(capture == 100);
    726                 },
    727             }
    728         }
    729     };
    730     try S.foo(42);
    731     try S.foo(100);
    732     try comptime S.foo(42);
    733     try comptime S.foo(100);
    734 }
    735 
    736 test "enum value without tag name used as switch item" {
    737     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    738 
    739     const E = enum(u32) {
    740         a = 1,
    741         b = 2,
    742         _,
    743     };
    744     var e: E = @enumFromInt(0);
    745     _ = &e;
    746     switch (e) {
    747         @as(E, @enumFromInt(0)) => {},
    748         .a => return error.TestFailed,
    749         .b => return error.TestFailed,
    750         _ => return error.TestFailed,
    751     }
    752 }
    753 
    754 test "switch item sizeof" {
    755     const S = struct {
    756         fn doTheTest() !void {
    757             var a: usize = 0;
    758             _ = &a;
    759             switch (a) {
    760                 @sizeOf(struct {}) => {},
    761                 else => return error.TestFailed,
    762             }
    763         }
    764     };
    765     try S.doTheTest();
    766     try comptime S.doTheTest();
    767 }
    768 
    769 test "comptime inline switch" {
    770     const U = union(enum) { a: type, b: type };
    771     const value = comptime blk: {
    772         var u: U = .{ .a = u32 };
    773         _ = &u;
    774         break :blk switch (u) {
    775             inline .a, .b => |v| v,
    776         };
    777     };
    778 
    779     try expectEqual(u32, value);
    780 }
    781 
    782 test "switch capture peer type resolution" {
    783     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    784 
    785     const U = union(enum) {
    786         a: u32,
    787         b: u64,
    788         fn innerVal(u: @This()) u64 {
    789             switch (u) {
    790                 .a, .b => |x| return x,
    791             }
    792         }
    793     };
    794 
    795     try expectEqual(@as(u64, 100), U.innerVal(.{ .a = 100 }));
    796     try expectEqual(@as(u64, 200), U.innerVal(.{ .b = 200 }));
    797 }
    798 
    799 test "switch capture peer type resolution for in-memory coercible payloads" {
    800     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    801 
    802     const T1 = c_int;
    803     const T2 = @Type(@typeInfo(T1));
    804 
    805     comptime assert(T1 != T2);
    806 
    807     const U = union(enum) {
    808         a: T1,
    809         b: T2,
    810         fn innerVal(u: @This()) c_int {
    811             switch (u) {
    812                 .a, .b => |x| return x,
    813             }
    814         }
    815     };
    816 
    817     try expectEqual(@as(c_int, 100), U.innerVal(.{ .a = 100 }));
    818     try expectEqual(@as(c_int, 200), U.innerVal(.{ .b = 200 }));
    819 }
    820 
    821 test "switch pointer capture peer type resolution" {
    822     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    823     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    824 
    825     const T1 = c_int;
    826     const T2 = @Type(@typeInfo(T1));
    827 
    828     comptime assert(T1 != T2);
    829 
    830     const U = union(enum) {
    831         a: T1,
    832         b: T2,
    833         fn innerVal(u: *@This()) *c_int {
    834             switch (u.*) {
    835                 .a, .b => |*ptr| return ptr,
    836             }
    837         }
    838     };
    839 
    840     var ua: U = .{ .a = 100 };
    841     var ub: U = .{ .b = 200 };
    842 
    843     ua.innerVal().* = 111;
    844     ub.innerVal().* = 222;
    845 
    846     try expectEqual(U{ .a = 111 }, ua);
    847     try expectEqual(U{ .b = 222 }, ub);
    848 }
    849 
    850 test "inline switch range that includes the maximum value of the switched type" {
    851     const inputs: [3]u8 = .{ 0, 254, 255 };
    852     for (inputs) |input| {
    853         switch (input) {
    854             inline 254...255 => |val| try expectEqual(input, val),
    855             else => |val| try expectEqual(input, val),
    856         }
    857     }
    858 }
    859 
    860 test "nested break ignores switch conditions and breaks instead" {
    861     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    862 
    863     const S = struct {
    864         fn register_to_address(ident: []const u8) !u8 {
    865             const reg: u8 = if (std.mem.eql(u8, ident, "zero")) 0x00 else blk: {
    866                 break :blk switch (ident[0]) {
    867                     0x61 => (try std.fmt.parseInt(u8, ident[1..], 0)) + 1,
    868                     0x66 => (try std.fmt.parseInt(u8, ident[1..], 0)) + 1,
    869                     else => {
    870                         break :blk 0xFF;
    871                     },
    872                 };
    873             };
    874             return reg;
    875         }
    876     };
    877     // Originally reported at https://github.com/ziglang/zig/issues/10196
    878     try expect(0x01 == try S.register_to_address("a0"));
    879 }
    880 
    881 test "peer type resolution on switch captures ignores unused payload bits" {
    882     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
    883     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    884 
    885     const Foo = union(enum) {
    886         a: u32,
    887         b: u64,
    888     };
    889 
    890     var val: Foo = undefined;
    891     @memset(std.mem.asBytes(&val), 0xFF);
    892 
    893     // This is runtime-known so the following store isn't comptime-known.
    894     var rt: u32 = 123;
    895     _ = &rt;
    896     val = .{ .a = rt }; // will not necessarily zero remaning payload memory
    897 
    898     // Fields intentionally backwards here
    899     const x = switch (val) {
    900         .b, .a => |x| x,
    901     };
    902 
    903     try expect(x == 123);
    904 }
    905 
    906 test "switch prong captures range" {
    907     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    908     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
    909 
    910     const S = struct {
    911         fn a(b: []u3, c: u3) void {
    912             switch (c) {
    913                 0...1 => b[c] = c,
    914                 2...3 => b[c] = c,
    915                 4...7 => |d| b[d] = c,
    916             }
    917         }
    918     };
    919 
    920     var arr: [8]u3 = undefined;
    921     S.a(&arr, 5);
    922     try expect(arr[5] == 5);
    923 }
    924 
    925 test "prong with inline call to unreachable" {
    926     if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
    927 
    928     const U = union(enum) {
    929         void: void,
    930         bool: bool,
    931 
    932         inline fn unreach() noreturn {
    933             unreachable;
    934         }
    935     };
    936     var u: U = undefined;
    937     u = .{ .bool = true };
    938     switch (u) {
    939         .void => U.unreach(),
    940         .bool => |ok| try expect(ok),
    941     }
    942 }
    943 
    944 test "block error return trace index is reset between prongs" {
    945     const S = struct {
    946         fn returnError() error{TestFailed} {
    947             return error.TestFailed;
    948         }
    949     };
    950 
    951     var x: u1 = 0;
    952     _ = &x;
    953 
    954     const result = switch (x) {
    955         0 => {
    956             const result: anyerror!i32 = blk: {
    957                 break :blk 1;
    958             };
    959             _ = &result;
    960         },
    961         1 => blk: {
    962             const err = switch (x) {
    963                 0 => {},
    964                 1 => S.returnError(),
    965             };
    966             break :blk err;
    967         },
    968     };
    969     try result;
    970 }