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