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 }