zig

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

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 }