blob dfd511af (27191B) - Raw
1 const builtin = @import("builtin"); 2 const std = @import("std"); 3 const expect = std.testing.expect; 4 const expectEqual = std.testing.expectEqual; 5 const mem = std.mem; 6 7 /// A more basic implementation of std.testing.expectError which 8 /// does not require formatter/printing support 9 fn expectError(expected_err: anyerror, observed_err_union: anytype) !void { 10 if (observed_err_union) |_| { 11 return error.TestExpectedError; 12 } else |err| if (err == expected_err) { 13 return; // Success 14 } 15 return error.TestExpectedError; 16 } 17 18 test "error values" { 19 const a = @intFromError(error.err1); 20 const b = @intFromError(error.err2); 21 try expect(a != b); 22 } 23 24 test "redefinition of error values allowed" { 25 shouldBeNotEqual(error.AnError, error.SecondError); 26 } 27 fn shouldBeNotEqual(a: anyerror, b: anyerror) void { 28 if (a == b) unreachable; 29 } 30 31 test "error binary operator" { 32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 33 34 const a = errBinaryOperatorG(true) catch 3; 35 const b = errBinaryOperatorG(false) catch 3; 36 try expect(a == 3); 37 try expect(b == 10); 38 } 39 fn errBinaryOperatorG(x: bool) anyerror!isize { 40 return if (x) error.ItBroke else @as(isize, 10); 41 } 42 43 test "empty error union" { 44 const x = error{} || error{}; 45 _ = x; 46 } 47 48 pub fn foo() anyerror!i32 { 49 const x = try bar(); 50 return x + 1; 51 } 52 53 pub fn bar() anyerror!i32 { 54 return 13; 55 } 56 57 pub fn baz() anyerror!i32 { 58 const y = foo() catch 1234; 59 return y + 1; 60 } 61 62 test "error wrapping" { 63 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 64 65 try expect((baz() catch unreachable) == 15); 66 } 67 68 test "unwrap simple value from error" { 69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 70 71 const i = unwrapSimpleValueFromErrorDo() catch unreachable; 72 try expect(i == 13); 73 } 74 fn unwrapSimpleValueFromErrorDo() anyerror!isize { 75 return 13; 76 } 77 78 test "error return in assignment" { 79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 80 81 doErrReturnInAssignment() catch unreachable; 82 } 83 84 fn doErrReturnInAssignment() anyerror!void { 85 var x: i32 = undefined; 86 x = try makeANonErr(); 87 } 88 89 fn makeANonErr() anyerror!i32 { 90 return 1; 91 } 92 93 test "syntax: optional operator in front of error union operator" { 94 comptime { 95 try expect(?(anyerror!i32) == ?(anyerror!i32)); 96 } 97 } 98 99 test "widen cast integer payload of error union function call" { 100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 102 103 const S = struct { 104 fn errorable() !u64 { 105 var x = @as(u64, try number()); 106 return x; 107 } 108 109 fn number() anyerror!u32 { 110 return 1234; 111 } 112 }; 113 try expect((try S.errorable()) == 1234); 114 } 115 116 test "debug info for optional error set" { 117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 119 120 const SomeError = error{ Hello, Hello2 }; 121 var a_local_variable: ?SomeError = null; 122 _ = a_local_variable; 123 } 124 125 test "implicit cast to optional to error union to return result loc" { 126 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 127 128 const S = struct { 129 fn entry() !void { 130 var x: Foo = undefined; 131 if (func(&x)) |opt| { 132 try expect(opt != null); 133 } else |_| @panic("expected non error"); 134 } 135 fn func(f: *Foo) anyerror!?*Foo { 136 return f; 137 } 138 const Foo = struct { 139 field: i32, 140 }; 141 }; 142 try S.entry(); 143 //comptime S.entry(); TODO 144 } 145 146 test "fn returning empty error set can be passed as fn returning any error" { 147 entry(); 148 comptime entry(); 149 } 150 151 test "fn returning empty error set can be passed as fn returning any error - pointer" { 152 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 153 entryPtr(); 154 comptime entryPtr(); 155 } 156 157 fn entry() void { 158 foo2(bar2); 159 } 160 161 fn entryPtr() void { 162 var ptr = &bar2; 163 fooPtr(ptr); 164 } 165 166 fn foo2(comptime f: fn () anyerror!void) void { 167 const x = f(); 168 x catch { 169 @panic("fail"); 170 }; 171 } 172 173 fn fooPtr(f: *const fn () anyerror!void) void { 174 const x = f(); 175 x catch { 176 @panic("fail"); 177 }; 178 } 179 180 fn bar2() (error{}!void) {} 181 182 test "error union type " { 183 try testErrorUnionType(); 184 try comptime testErrorUnionType(); 185 } 186 187 fn testErrorUnionType() !void { 188 const x: anyerror!i32 = 1234; 189 if (x) |value| try expect(value == 1234) else |_| unreachable; 190 try expect(@typeInfo(@TypeOf(x)) == .ErrorUnion); 191 try expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet); 192 try expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror); 193 } 194 195 test "error set type" { 196 try testErrorSetType(); 197 try comptime testErrorSetType(); 198 } 199 200 const MyErrSet = error{ 201 OutOfMemory, 202 FileNotFound, 203 }; 204 205 fn testErrorSetType() !void { 206 try expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2); 207 208 const a: MyErrSet!i32 = 5678; 209 const b: MyErrSet!i32 = MyErrSet.OutOfMemory; 210 try expect(b catch error.OutOfMemory == error.OutOfMemory); 211 212 if (a) |value| try expect(value == 5678) else |err| switch (err) { 213 error.OutOfMemory => unreachable, 214 error.FileNotFound => unreachable, 215 } 216 } 217 218 test "explicit error set cast" { 219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 220 221 try testExplicitErrorSetCast(Set1.A); 222 try comptime testExplicitErrorSetCast(Set1.A); 223 } 224 225 const Set1 = error{ A, B }; 226 const Set2 = error{ A, C }; 227 228 fn testExplicitErrorSetCast(set1: Set1) !void { 229 var x = @as(Set2, @errorCast(set1)); 230 try expect(@TypeOf(x) == Set2); 231 var y = @as(Set1, @errorCast(x)); 232 try expect(@TypeOf(y) == Set1); 233 try expect(y == error.A); 234 } 235 236 test "@errorCast on error unions" { 237 const S = struct { 238 fn doTheTest() !void { 239 { 240 const casted: error{Bad}!i32 = @errorCast(retErrUnion()); 241 try expect((try casted) == 1234); 242 } 243 { 244 const casted: error{Bad}!i32 = @errorCast(retInferredErrUnion()); 245 try expect((try casted) == 5678); 246 } 247 } 248 249 fn retErrUnion() anyerror!i32 { 250 return 1234; 251 } 252 253 fn retInferredErrUnion() !i32 { 254 return 5678; 255 } 256 }; 257 258 try S.doTheTest(); 259 try comptime S.doTheTest(); 260 } 261 262 test "comptime test error for empty error set" { 263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 264 265 try testComptimeTestErrorEmptySet(1234); 266 try comptime testComptimeTestErrorEmptySet(1234); 267 } 268 269 const EmptyErrorSet = error{}; 270 271 fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void { 272 if (x) |v| try expect(v == 1234) else |err| { 273 _ = err; 274 @compileError("bad"); 275 } 276 } 277 278 test "comptime err to int of error set with only 1 possible value" { 279 testErrToIntWithOnePossibleValue(error.A, @intFromError(error.A)); 280 comptime testErrToIntWithOnePossibleValue(error.A, @intFromError(error.A)); 281 } 282 fn testErrToIntWithOnePossibleValue( 283 x: error{A}, 284 comptime value: u32, 285 ) void { 286 if (@intFromError(x) != value) { 287 @compileError("bad"); 288 } 289 } 290 291 test "inferred empty error set comptime catch" { 292 const S = struct { 293 fn foo() !void {} 294 }; 295 S.foo() catch @compileError("fail"); 296 } 297 298 test "error inference with an empty set" { 299 const S = struct { 300 const Struct = struct { 301 pub fn func() (error{})!usize { 302 return 0; 303 } 304 }; 305 306 fn AnotherStruct(comptime SubStruct: type) type { 307 return struct { 308 fn anotherFunc() !void { 309 try expect(0 == (try SubStruct.func())); 310 } 311 }; 312 } 313 }; 314 315 const GeneratedStruct = S.AnotherStruct(S.Struct); 316 try GeneratedStruct.anotherFunc(); 317 } 318 319 test "error union peer type resolution" { 320 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 321 322 try testErrorUnionPeerTypeResolution(1); 323 } 324 325 fn testErrorUnionPeerTypeResolution(x: i32) !void { 326 const y = switch (x) { 327 1 => bar_1(), 328 2 => baz_1(), 329 else => quux_1(), 330 }; 331 if (y) |_| { 332 @panic("expected error"); 333 } else |e| { 334 try expect(e == error.A); 335 } 336 } 337 338 fn bar_1() anyerror { 339 return error.A; 340 } 341 342 fn baz_1() !i32 { 343 return error.B; 344 } 345 346 fn quux_1() !i32 { 347 return error.C; 348 } 349 350 test "error: Zero sized error set returned with value payload crash" { 351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 352 353 _ = try foo3(0); 354 _ = try comptime foo3(0); 355 } 356 357 const Error = error{}; 358 fn foo3(b: usize) Error!usize { 359 return b; 360 } 361 362 test "error: Infer error set from literals" { 363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 364 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 365 366 _ = nullLiteral("n") catch |err| handleErrors(err); 367 _ = floatLiteral("n") catch |err| handleErrors(err); 368 _ = intLiteral("n") catch |err| handleErrors(err); 369 _ = comptime nullLiteral("n") catch |err| handleErrors(err); 370 _ = comptime floatLiteral("n") catch |err| handleErrors(err); 371 _ = comptime intLiteral("n") catch |err| handleErrors(err); 372 } 373 374 fn handleErrors(err: anytype) noreturn { 375 switch (err) { 376 error.T => {}, 377 } 378 379 unreachable; 380 } 381 382 fn nullLiteral(str: []const u8) !?i64 { 383 if (str[0] == 'n') return null; 384 385 return error.T; 386 } 387 388 fn floatLiteral(str: []const u8) !?f64 { 389 if (str[0] == 'n') return 1.0; 390 391 return error.T; 392 } 393 394 fn intLiteral(str: []const u8) !?i64 { 395 if (str[0] == 'n') return 1; 396 397 return error.T; 398 } 399 400 test "nested error union function call in optional unwrap" { 401 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 402 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 403 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 404 405 const S = struct { 406 const Foo = struct { 407 a: i32, 408 }; 409 410 fn errorable() !i32 { 411 var x: Foo = (try getFoo()) orelse return error.Other; 412 return x.a; 413 } 414 415 fn errorable2() !i32 { 416 var x: Foo = (try getFoo2()) orelse return error.Other; 417 return x.a; 418 } 419 420 fn errorable3() !i32 { 421 var x: Foo = (try getFoo3()) orelse return error.Other; 422 return x.a; 423 } 424 425 fn getFoo() anyerror!?Foo { 426 return Foo{ .a = 1234 }; 427 } 428 429 fn getFoo2() anyerror!?Foo { 430 return error.Failure; 431 } 432 433 fn getFoo3() anyerror!?Foo { 434 return null; 435 } 436 }; 437 try expect((try S.errorable()) == 1234); 438 try expectError(error.Failure, S.errorable2()); 439 try expectError(error.Other, S.errorable3()); 440 comptime { 441 try expect((try S.errorable()) == 1234); 442 try expectError(error.Failure, S.errorable2()); 443 try expectError(error.Other, S.errorable3()); 444 } 445 } 446 447 test "return function call to error set from error union function" { 448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 449 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 450 451 const S = struct { 452 fn errorable() anyerror!i32 { 453 return fail(); 454 } 455 456 fn fail() anyerror { 457 return error.Failure; 458 } 459 }; 460 try expectError(error.Failure, S.errorable()); 461 try comptime expectError(error.Failure, S.errorable()); 462 } 463 464 test "optional error set is the same size as error set" { 465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 468 469 try comptime expect(@sizeOf(?anyerror) == @sizeOf(anyerror)); 470 try comptime expect(@alignOf(?anyerror) == @alignOf(anyerror)); 471 const S = struct { 472 fn returnsOptErrSet() ?anyerror { 473 return null; 474 } 475 }; 476 try expect(S.returnsOptErrSet() == null); 477 try comptime expect(S.returnsOptErrSet() == null); 478 } 479 480 test "nested catch" { 481 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 482 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 483 484 const S = struct { 485 fn entry() !void { 486 try expectError(error.Bad, func()); 487 } 488 fn fail() anyerror!Foo { 489 return error.Wrong; 490 } 491 fn func() anyerror!Foo { 492 _ = fail() catch 493 fail() catch 494 return error.Bad; 495 unreachable; 496 } 497 const Foo = struct { 498 field: i32, 499 }; 500 }; 501 try S.entry(); 502 try comptime S.entry(); 503 } 504 505 test "function pointer with return type that is error union with payload which is pointer of parent struct" { 506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 507 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 508 509 const S = struct { 510 const Foo = struct { 511 fun: *const fn (a: i32) (anyerror!*Foo), 512 }; 513 514 const Err = error{UnspecifiedErr}; 515 516 fn bar(a: i32) anyerror!*Foo { 517 _ = a; 518 return Err.UnspecifiedErr; 519 } 520 521 fn doTheTest() !void { 522 var x = Foo{ .fun = @This().bar }; 523 try expectError(error.UnspecifiedErr, x.fun(1)); 524 } 525 }; 526 try S.doTheTest(); 527 } 528 529 test "return result loc as peer result loc in inferred error set function" { 530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 532 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 533 534 const S = struct { 535 fn doTheTest() !void { 536 if (quux(2)) |x| { 537 try expect(x.Two); 538 } else |e| switch (e) { 539 error.Whatever => @panic("fail"), 540 } 541 try expectError(error.Whatever, quux(99)); 542 } 543 const FormValue = union(enum) { 544 One: void, 545 Two: bool, 546 }; 547 548 fn quux(id: u64) !FormValue { 549 return switch (id) { 550 2 => FormValue{ .Two = true }, 551 1 => FormValue{ .One = {} }, 552 else => return error.Whatever, 553 }; 554 } 555 }; 556 try S.doTheTest(); 557 try comptime S.doTheTest(); 558 } 559 560 test "error payload type is correctly resolved" { 561 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 562 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 563 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 564 565 const MyIntWrapper = struct { 566 const Self = @This(); 567 568 x: i32, 569 570 pub fn create() anyerror!Self { 571 return Self{ .x = 42 }; 572 } 573 }; 574 575 try expect(std.meta.eql(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create())); 576 } 577 578 test "error union comptime caching" { 579 const S = struct { 580 fn quux(comptime arg: anytype) void { 581 arg catch {}; 582 } 583 }; 584 585 S.quux(@as(anyerror!void, {})); 586 S.quux(@as(anyerror!void, {})); 587 } 588 589 test "@errorName" { 590 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 591 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 592 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 593 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 594 595 try expect(mem.eql(u8, @errorName(error.AnError), "AnError")); 596 try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); 597 try expect(mem.eql(u8, @errorName(gimmeItBroke()), "ItBroke")); 598 } 599 fn gimmeItBroke() anyerror { 600 return error.ItBroke; 601 } 602 603 test "@errorName sentinel length matches slice length" { 604 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 605 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 606 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 607 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 608 609 const name = testBuiltinErrorName(error.FooBar); 610 const length: usize = 6; 611 try expect(length == std.mem.indexOfSentinel(u8, 0, name.ptr)); 612 try expect(length == name.len); 613 } 614 615 pub fn testBuiltinErrorName(err: anyerror) [:0]const u8 { 616 return @errorName(err); 617 } 618 619 test "error set equality" { 620 const a = error{One}; 621 const b = error{One}; 622 623 try expect(a == a); 624 try expect(a == b); 625 try expect(a == error{One}); 626 627 // should treat as a set 628 const c = error{ One, Two }; 629 const d = error{ Two, One }; 630 631 try expect(c == d); 632 } 633 634 test "inferred error set equality" { 635 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 636 637 const S = struct { 638 fn foo() !void { 639 return @This().bar(); 640 } 641 642 fn bar() !void { 643 return error.Bad; 644 } 645 646 fn baz() !void { 647 return quux(); 648 } 649 650 fn quux() anyerror!void {} 651 }; 652 653 const FooError = @typeInfo(@typeInfo(@TypeOf(S.foo)).Fn.return_type.?).ErrorUnion.error_set; 654 const BarError = @typeInfo(@typeInfo(@TypeOf(S.bar)).Fn.return_type.?).ErrorUnion.error_set; 655 const BazError = @typeInfo(@typeInfo(@TypeOf(S.baz)).Fn.return_type.?).ErrorUnion.error_set; 656 657 try expect(BarError != error{Bad}); 658 659 try expect(FooError != anyerror); 660 try expect(BarError != anyerror); 661 try expect(BazError != anyerror); 662 663 try expect(FooError != BarError); 664 try expect(FooError != BazError); 665 try expect(BarError != BazError); 666 667 try expect(FooError == FooError); 668 try expect(BarError == BarError); 669 try expect(BazError == BazError); 670 } 671 672 test "peer type resolution of two different error unions" { 673 const a: error{B}!void = {}; 674 const b: error{A}!void = {}; 675 var cond = true; 676 const err = if (cond) a else b; 677 try err; 678 } 679 680 test "coerce error set to the current inferred error set" { 681 const S = struct { 682 fn foo() !void { 683 var a = false; 684 if (a) { 685 const b: error{A}!void = error.A; 686 return b; 687 } 688 const b = error.A; 689 return b; 690 } 691 }; 692 S.foo() catch {}; 693 } 694 695 test "error union payload is properly aligned" { 696 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 697 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 698 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 699 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 700 701 const S = struct { 702 a: u128, 703 b: u128, 704 c: u128, 705 fn foo() error{}!@This() { 706 return @This(){ .a = 1, .b = 2, .c = 3 }; 707 } 708 }; 709 const blk = S.foo() catch unreachable; 710 if (blk.a != 1) unreachable; 711 } 712 713 test "ret_ptr doesn't cause own inferred error set to be resolved" { 714 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 715 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 716 717 const S = struct { 718 fn foo() !void {} 719 720 fn doTheTest() !void { 721 errdefer @compileError("bad"); 722 723 return try @This().foo(); 724 } 725 }; 726 try S.doTheTest(); 727 } 728 729 test "simple else prong allowed even when all errors handled" { 730 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 731 732 const S = struct { 733 fn foo() !u8 { 734 return error.Foo; 735 } 736 }; 737 var value = S.foo() catch |err| switch (err) { 738 error.Foo => @as(u8, 255), 739 else => |e| return e, 740 }; 741 try expect(value == 255); 742 value = S.foo() catch |err| switch (err) { 743 error.Foo => 255, 744 else => unreachable, 745 }; 746 try expect(value == 255); 747 value = S.foo() catch |err| switch (err) { 748 error.Foo => 255, 749 else => return, 750 }; 751 try expect(value == 255); 752 } 753 754 test "pointer to error union payload" { 755 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 758 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 759 760 var err_union: anyerror!u8 = 15; 761 762 const payload_ptr = &(err_union catch unreachable); 763 try expect(payload_ptr.* == 15); 764 } 765 766 const NoReturn = struct { 767 var a: u32 = undefined; 768 fn someData() bool { 769 a -= 1; 770 return a == 0; 771 } 772 fn loop() !noreturn { 773 while (true) { 774 if (someData()) 775 return error.GenericFailure; 776 } 777 } 778 fn testTry() anyerror { 779 try loop(); 780 } 781 fn testCatch() anyerror { 782 loop() catch return error.OtherFailure; 783 @compileError("bad"); 784 } 785 }; 786 787 test "error union of noreturn used with if" { 788 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 789 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 790 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 791 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 792 793 NoReturn.a = 64; 794 if (NoReturn.loop()) { 795 @compileError("bad"); 796 } else |err| { 797 try expect(err == error.GenericFailure); 798 } 799 } 800 801 test "error union of noreturn used with try" { 802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 803 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 804 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 805 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 806 807 NoReturn.a = 64; 808 const err = NoReturn.testTry(); 809 try expect(err == error.GenericFailure); 810 } 811 812 test "error union of noreturn used with catch" { 813 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 815 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 816 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 817 818 NoReturn.a = 64; 819 const err = NoReturn.testCatch(); 820 try expect(err == error.OtherFailure); 821 } 822 823 test "alignment of wrapping an error union payload" { 824 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 825 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 826 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 827 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 828 829 const S = struct { 830 const I = extern struct { x: i128 }; 831 832 fn foo() anyerror!I { 833 var i: I = .{ .x = 1234 }; 834 return i; 835 } 836 }; 837 try expect((S.foo() catch unreachable).x == 1234); 838 } 839 840 test "compare error union and error set" { 841 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 842 843 var a: anyerror = error.Foo; 844 var b: anyerror!u32 = error.Bar; 845 846 try expect(a != b); 847 try expect(b != a); 848 849 b = error.Foo; 850 851 try expect(a == b); 852 try expect(b == a); 853 854 b = 2; 855 856 try expect(a != b); 857 try expect(b != a); 858 } 859 860 fn non_errorable() void { 861 // Make sure catch works even in a function that does not call any errorable functions. 862 // 863 // This test is needed because stage 2's fix for #1923 means that catch blocks interact 864 // with the error return trace index. 865 var x: error{Foo}!void = {}; 866 return x catch {}; 867 } 868 869 test "catch within a function that calls no errorable functions" { 870 non_errorable(); 871 } 872 873 test "error from comptime string" { 874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 877 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 878 879 const name = "Weird error name!"; 880 const S = struct { 881 fn foo() !void { 882 return @field(anyerror, name); 883 } 884 }; 885 if (S.foo()) unreachable else |err| { 886 try expect(mem.eql(u8, name, @errorName(err))); 887 } 888 } 889 890 test "field access of anyerror results in smaller error set" { 891 const E1 = @TypeOf(error.Foo); 892 try expect(@TypeOf(E1.Foo) == E1); 893 const E2 = error{ A, B, C }; 894 try expect(@TypeOf(E2.A) == E2); 895 try expect(@TypeOf(@field(anyerror, "NotFound")) == error{NotFound}); 896 } 897 898 test "optional error union return type" { 899 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 900 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 901 902 const S = struct { 903 fn foo() ?anyerror!u32 { 904 var x: u32 = 1234; 905 return @as(anyerror!u32, x); 906 } 907 }; 908 try expect(1234 == try S.foo().?); 909 } 910 911 test "optional error set return type" { 912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 913 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 914 915 const E = error{ A, B }; 916 const S = struct { 917 fn foo(return_null: bool) ?E { 918 return if (return_null) null else E.A; 919 } 920 }; 921 922 try expect(null == S.foo(true)); 923 try expect(E.A == S.foo(false).?); 924 } 925 926 test "returning an error union containing a type with no runtime bits" { 927 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 928 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 929 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; 930 931 const ZeroByteType = struct { 932 foo: void, 933 934 pub fn init() !@This() { 935 return .{ .foo = {} }; 936 } 937 }; 938 939 var zero_byte: ZeroByteType = undefined; 940 (&zero_byte).* = try ZeroByteType.init(); 941 } 942 943 test "try used in recursive function with inferred error set" { 944 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 946 947 const Value = union(enum) { 948 values: []const @This(), 949 b, 950 951 fn x(value: @This()) !void { 952 switch (value.values[0]) { 953 .values => return try x(value.values[0]), 954 .b => return error.a, 955 } 956 } 957 }; 958 const a = Value{ 959 .values = &[1]Value{ 960 .{ 961 .values = &[1]Value{.{ .b = {} }}, 962 }, 963 }, 964 }; 965 try expectError(error.a, Value.x(a)); 966 }