master
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}
158
159fn entry() void {
160 foo2(bar2);
161}
162
163fn entryPtr() void {
164 var ptr = &bar2;
165 _ = &ptr;
166 fooPtr(ptr);
167}
168
169fn foo2(comptime f: fn () anyerror!void) void {
170 const x = f();
171 x catch {
172 @panic("fail");
173 };
174}
175
176fn fooPtr(f: *const fn () anyerror!void) void {
177 const x = f();
178 x catch {
179 @panic("fail");
180 };
181}
182
183fn bar2() (error{}!void) {}
184
185test "error union type " {
186 try testErrorUnionType();
187 try comptime testErrorUnionType();
188}
189
190fn testErrorUnionType() !void {
191 const x: anyerror!i32 = 1234;
192 if (x) |value| try expect(value == 1234) else |_| unreachable;
193 try expect(@typeInfo(@TypeOf(x)) == .error_union);
194 try expect(@typeInfo(@typeInfo(@TypeOf(x)).error_union.error_set) == .error_set);
195 try expect(@typeInfo(@TypeOf(x)).error_union.error_set == anyerror);
196}
197
198test "error set type" {
199 try testErrorSetType();
200 try comptime testErrorSetType();
201}
202
203const MyErrSet = error{
204 OutOfMemory,
205 FileNotFound,
206};
207
208fn testErrorSetType() !void {
209 try expect(@typeInfo(MyErrSet).error_set.?.len == 2);
210
211 const a: MyErrSet!i32 = 5678;
212 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
213 try expect(b catch error.OutOfMemory == error.OutOfMemory);
214
215 if (a) |value| try expect(value == 5678) else |err| switch (err) {
216 error.OutOfMemory => unreachable,
217 error.FileNotFound => unreachable,
218 }
219}
220
221test "explicit error set cast" {
222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223
224 try testExplicitErrorSetCast(Set1.A);
225 try comptime testExplicitErrorSetCast(Set1.A);
226}
227
228const Set1 = error{ A, B };
229const Set2 = error{ A, C };
230
231fn testExplicitErrorSetCast(set1: Set1) !void {
232 const x: Set2 = @errorCast(set1);
233 try expect(@TypeOf(x) == Set2);
234 const y: Set1 = @errorCast(x);
235 try expect(@TypeOf(y) == Set1);
236 try expect(y == error.A);
237}
238
239test "@errorCast on error unions" {
240 const S = struct {
241 fn doTheTest() !void {
242 {
243 const casted: error{Bad}!i32 = @errorCast(retErrUnion());
244 try expect((try casted) == 1234);
245 }
246 {
247 const casted: error{Bad}!i32 = @errorCast(retInferredErrUnion());
248 try expect((try casted) == 5678);
249 }
250 }
251
252 fn retErrUnion() anyerror!i32 {
253 return 1234;
254 }
255
256 fn retInferredErrUnion() !i32 {
257 return 5678;
258 }
259 };
260
261 try S.doTheTest();
262 try comptime S.doTheTest();
263}
264
265test "comptime test error for empty error set" {
266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
267
268 try testComptimeTestErrorEmptySet(1234);
269 try comptime testComptimeTestErrorEmptySet(1234);
270}
271
272const EmptyErrorSet = error{};
273
274fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
275 if (x) |v| try expect(v == 1234) else |err| {
276 _ = err;
277 @compileError("bad");
278 }
279}
280
281test "comptime err to int of error set with only 1 possible value" {
282 testErrToIntWithOnePossibleValue(error.A, @intFromError(error.A));
283 comptime testErrToIntWithOnePossibleValue(error.A, @intFromError(error.A));
284}
285fn testErrToIntWithOnePossibleValue(
286 x: error{A},
287 comptime value: u32,
288) void {
289 if (@intFromError(x) != value) {
290 @compileError("bad");
291 }
292}
293
294test "inferred empty error set comptime catch" {
295 const S = struct {
296 fn foo() !void {}
297 };
298 S.foo() catch @compileError("fail");
299}
300
301test "error inference with an empty set" {
302 const S = struct {
303 const Struct = struct {
304 pub fn func() (error{})!usize {
305 return 0;
306 }
307 };
308
309 fn AnotherStruct(comptime SubStruct: type) type {
310 return struct {
311 fn anotherFunc() !void {
312 try expect(0 == (try SubStruct.func()));
313 }
314 };
315 }
316 };
317
318 const GeneratedStruct = S.AnotherStruct(S.Struct);
319 try GeneratedStruct.anotherFunc();
320}
321
322test "error union peer type resolution" {
323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
324
325 try testErrorUnionPeerTypeResolution(1);
326}
327
328fn testErrorUnionPeerTypeResolution(x: i32) !void {
329 const y = switch (x) {
330 1 => bar_1(),
331 2 => baz_1(),
332 else => quux_1(),
333 };
334 if (y) |_| {
335 @panic("expected error");
336 } else |e| {
337 try expect(e == error.A);
338 }
339}
340
341fn bar_1() anyerror {
342 return error.A;
343}
344
345fn baz_1() !i32 {
346 return error.B;
347}
348
349fn quux_1() !i32 {
350 return error.C;
351}
352
353test "error: Zero sized error set returned with value payload crash" {
354 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
355
356 _ = try foo3(0);
357 _ = try comptime foo3(0);
358}
359
360const Error = error{};
361fn foo3(b: usize) Error!usize {
362 return b;
363}
364
365test "error: Infer error set from literals" {
366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
368
369 _ = nullLiteral("n") catch |err| handleErrors(err);
370 _ = floatLiteral("n") catch |err| handleErrors(err);
371 _ = intLiteral("n") catch |err| handleErrors(err);
372 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
373 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
374 _ = comptime intLiteral("n") catch |err| handleErrors(err);
375}
376
377fn handleErrors(err: anytype) noreturn {
378 switch (err) {
379 error.T => {},
380 }
381
382 unreachable;
383}
384
385fn nullLiteral(str: []const u8) !?i64 {
386 if (str[0] == 'n') return null;
387
388 return error.T;
389}
390
391fn floatLiteral(str: []const u8) !?f64 {
392 if (str[0] == 'n') return 1.0;
393
394 return error.T;
395}
396
397fn intLiteral(str: []const u8) !?i64 {
398 if (str[0] == 'n') return 1;
399
400 return error.T;
401}
402
403test "nested error union function call in optional unwrap" {
404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406
407 const S = struct {
408 const Foo = struct {
409 a: i32,
410 };
411
412 fn errorable() !i32 {
413 const x: Foo = (try getFoo()) orelse return error.Other;
414 return x.a;
415 }
416
417 fn errorable2() !i32 {
418 const x: Foo = (try getFoo2()) orelse return error.Other;
419 return x.a;
420 }
421
422 fn errorable3() !i32 {
423 const x: Foo = (try getFoo3()) orelse return error.Other;
424 return x.a;
425 }
426
427 fn getFoo() anyerror!?Foo {
428 return Foo{ .a = 1234 };
429 }
430
431 fn getFoo2() anyerror!?Foo {
432 return error.Failure;
433 }
434
435 fn getFoo3() anyerror!?Foo {
436 return null;
437 }
438 };
439 try expect((try S.errorable()) == 1234);
440 try expectError(error.Failure, S.errorable2());
441 try expectError(error.Other, S.errorable3());
442 comptime {
443 try expect((try S.errorable()) == 1234);
444 try expectError(error.Failure, S.errorable2());
445 try expectError(error.Other, S.errorable3());
446 }
447}
448
449test "return function call to error set from error union function" {
450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
451
452 const S = struct {
453 fn errorable() anyerror!i32 {
454 return fail();
455 }
456
457 fn fail() anyerror {
458 return error.Failure;
459 }
460 };
461 try expectError(error.Failure, S.errorable());
462 comptime assert(error.Failure == S.errorable());
463}
464
465test "optional error set is the same size as error set" {
466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
468
469 comptime assert(@sizeOf(?anyerror) == @sizeOf(anyerror));
470 comptime assert(@alignOf(?anyerror) == @alignOf(anyerror));
471 const S = struct {
472 fn returnsOptErrSet() ?anyerror {
473 return null;
474 }
475 };
476 try expect(S.returnsOptErrSet() == null);
477 comptime assert(S.returnsOptErrSet() == null);
478}
479
480test "nested catch" {
481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482
483 const S = struct {
484 fn entry() !void {
485 try expectError(error.Bad, func());
486 }
487 fn fail() anyerror!Foo {
488 return error.Wrong;
489 }
490 fn func() anyerror!Foo {
491 _ = fail() catch
492 fail() catch
493 return error.Bad;
494 unreachable;
495 }
496 const Foo = struct {
497 field: i32,
498 };
499 };
500 try S.entry();
501 try comptime S.entry();
502}
503
504test "function pointer with return type that is error union with payload which is pointer of parent struct" {
505 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
507
508 const S = struct {
509 const Foo = struct {
510 fun: *const fn (a: i32) (anyerror!*Foo),
511 };
512
513 const Err = error{UnspecifiedErr};
514
515 fn bar(a: i32) anyerror!*Foo {
516 _ = a;
517 return Err.UnspecifiedErr;
518 }
519
520 fn doTheTest() !void {
521 var x = Foo{ .fun = @This().bar };
522 try expectError(error.UnspecifiedErr, x.fun(1));
523 }
524 };
525 try S.doTheTest();
526}
527
528test "return result loc as peer result loc in inferred error set function" {
529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
530 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
532
533 const S = struct {
534 fn doTheTest() !void {
535 if (quux(2)) |x| {
536 try expect(x.Two);
537 } else |e| switch (e) {
538 error.Whatever => @panic("fail"),
539 }
540 try expectError(error.Whatever, quux(99));
541 }
542 const FormValue = union(enum) {
543 One: void,
544 Two: bool,
545 };
546
547 fn quux(id: u64) !FormValue {
548 return switch (id) {
549 2 => FormValue{ .Two = true },
550 1 => FormValue{ .One = {} },
551 else => return error.Whatever,
552 };
553 }
554 };
555 try S.doTheTest();
556 try comptime S.doTheTest();
557}
558
559test "error payload type is correctly resolved" {
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_spirv) return error.SkipZigTest;
699 if (builtin.zig_backend == .stage2_riscv64) 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
713test "ret_ptr doesn't cause own inferred error set to be resolved" {
714 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
715
716 const S = struct {
717 fn foo() !void {}
718
719 fn doTheTest() !void {
720 errdefer @compileError("bad");
721
722 return try @This().foo();
723 }
724 };
725 try S.doTheTest();
726}
727
728test "simple else prong allowed even when all errors handled" {
729 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
730
731 const S = struct {
732 fn foo() !u8 {
733 return error.Foo;
734 }
735 };
736 var value = S.foo() catch |err| switch (err) {
737 error.Foo => @as(u8, 255),
738 else => |e| return e,
739 };
740 try expect(value == 255);
741 value = S.foo() catch |err| switch (err) {
742 error.Foo => 255,
743 else => unreachable,
744 };
745 try expect(value == 255);
746 value = S.foo() catch |err| switch (err) {
747 error.Foo => 255,
748 else => return,
749 };
750 try expect(value == 255);
751}
752
753test "pointer to error union payload" {
754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
756 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
757 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
758
759 var err_union: anyerror!u8 = 15;
760
761 const payload_ptr = &(err_union catch unreachable);
762 try expect(payload_ptr.* == 15);
763}
764
765const NoReturn = struct {
766 var a: u32 = undefined;
767 fn someData() bool {
768 a -= 1;
769 return a == 0;
770 }
771 fn loop() !noreturn {
772 while (true) {
773 if (someData())
774 return error.GenericFailure;
775 }
776 }
777 fn testTry() anyerror {
778 try loop();
779 }
780 fn testCatch() anyerror {
781 loop() catch return error.OtherFailure;
782 @compileError("bad");
783 }
784};
785
786test "error union of noreturn used with if" {
787 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
788 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
789 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
790 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
791
792 NoReturn.a = 64;
793 if (NoReturn.loop()) {
794 @compileError("bad");
795 } else |err| {
796 try expect(err == error.GenericFailure);
797 }
798}
799
800test "error union of noreturn used with try" {
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
804 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
805
806 NoReturn.a = 64;
807 const err = NoReturn.testTry();
808 try expect(err == error.GenericFailure);
809}
810
811test "error union of noreturn used with catch" {
812 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
815 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
816
817 NoReturn.a = 64;
818 const err = NoReturn.testCatch();
819 try expect(err == error.OtherFailure);
820}
821
822test "alignment of wrapping an error union payload" {
823 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
824 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
825 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
826 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
827
828 const S = struct {
829 const I = extern struct { x: i128 };
830
831 fn foo() anyerror!I {
832 var i: I = .{ .x = 1234 };
833 _ = &i;
834 return i;
835 }
836 };
837 try expect((S.foo() catch unreachable).x == 1234);
838}
839
840test "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 _ = &a;
846
847 try expect(a != b);
848 try expect(b != a);
849
850 b = error.Foo;
851
852 try expect(a == b);
853 try expect(b == a);
854
855 b = 2;
856
857 try expect(a != b);
858 try expect(b != a);
859}
860
861fn non_errorable() void {
862 // Make sure catch works even in a function that does not call any errorable functions.
863 //
864 // This test is needed because stage 2's fix for #1923 means that catch blocks interact
865 // with the error return trace index.
866 var x: error{Foo}!void = {};
867 _ = &x;
868 return x catch {};
869}
870
871test "catch within a function that calls no errorable functions" {
872 non_errorable();
873}
874
875test "error from comptime string" {
876 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
877 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
878 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
879 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
880
881 const name = "Weird error name!";
882 const S = struct {
883 fn foo() !void {
884 return @field(anyerror, name);
885 }
886 };
887 if (S.foo()) unreachable else |err| {
888 try expect(mem.eql(u8, name, @errorName(err)));
889 }
890}
891
892test "field access of anyerror results in smaller error set" {
893 const E1 = @TypeOf(error.Foo);
894 try expect(@TypeOf(E1.Foo) == E1);
895 const E2 = error{ A, B, C };
896 try expect(@TypeOf(E2.A) == E2);
897 try expect(@TypeOf(@field(anyerror, "NotFound")) == error{NotFound});
898}
899
900test "optional error union return type" {
901 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
902
903 const S = struct {
904 fn foo() ?anyerror!u32 {
905 var x: u32 = 1234;
906 _ = &x;
907 return @as(anyerror!u32, x);
908 }
909 };
910 try expect(1234 == try S.foo().?);
911}
912
913test "optional error set return type" {
914 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
915
916 const E = error{ A, B };
917 const S = struct {
918 fn foo(return_null: bool) ?E {
919 return if (return_null) null else E.A;
920 }
921 };
922
923 try expect(null == S.foo(true));
924 try expect(E.A == S.foo(false).?);
925}
926
927test "optional error set function parameter" {
928 const S = struct {
929 fn doTheTest(a: ?anyerror) !void {
930 try std.testing.expect(a.? == error.OutOfMemory);
931 }
932 };
933 try S.doTheTest(error.OutOfMemory);
934 try comptime S.doTheTest(error.OutOfMemory);
935}
936
937test "returning an error union containing a type with no runtime bits" {
938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
939 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
940
941 const ZeroByteType = struct {
942 foo: void,
943
944 pub fn init() !@This() {
945 return .{ .foo = {} };
946 }
947 };
948
949 var zero_byte: ZeroByteType = undefined;
950 (&zero_byte).* = try ZeroByteType.init();
951}
952
953test "try used in recursive function with inferred error set" {
954 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
955 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
956
957 const Value = union(enum) {
958 values: []const @This(),
959 b,
960
961 fn x(value: @This()) !void {
962 switch (value.values[0]) {
963 .values => return try x(value.values[0]),
964 .b => return error.a,
965 }
966 }
967 };
968 const a = Value{
969 .values = &[1]Value{
970 .{
971 .values = &[1]Value{.{ .b = {} }},
972 },
973 },
974 };
975 try expectError(error.a, Value.x(a));
976}
977
978test "generic inline function returns inferred error set" {
979 const S = struct {
980 inline fn retErr(comptime T: type) !T {
981 return error.AnError;
982 }
983
984 fn main0() !void {
985 _ = try retErr(u8);
986 }
987 };
988 S.main0() catch |e| {
989 try std.testing.expect(e == error.AnError);
990 };
991}
992
993test "function called at runtime is properly analyzed for inferred error set" {
994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
996
997 const S = struct {
998 fn foo() !void {
999 var a = true;
1000 _ = &a;
1001 if (a) return error.Foo;
1002 return error.Bar;
1003 }
1004 fn bar() !void {
1005 try @This().foo();
1006 }
1007 };
1008
1009 S.bar() catch |err| switch (err) {
1010 error.Foo => {},
1011 error.Bar => {},
1012 };
1013}
1014
1015test "errorCast to adhoc inferred error set" {
1016 const S = struct {
1017 inline fn baz() !i32 {
1018 return @errorCast(err());
1019 }
1020 fn err() anyerror!i32 {
1021 return 1234;
1022 }
1023 };
1024 try std.testing.expect((try S.baz()) == 1234);
1025}
1026
1027test "@errorCast from error set to error union" {
1028 const S = struct {
1029 fn doTheTest(set: error{ A, B }) error{A}!i32 {
1030 return @errorCast(set);
1031 }
1032 };
1033 try expectError(error.A, S.doTheTest(error.A));
1034 try expectError(error.A, comptime S.doTheTest(error.A));
1035}
1036
1037test "@errorCast from error union to error union" {
1038 const S = struct {
1039 fn doTheTest(set: error{ A, B }!i32) error{A}!i32 {
1040 return @errorCast(set);
1041 }
1042 };
1043 try expectError(error.A, S.doTheTest(error.A));
1044 try expectError(error.A, comptime S.doTheTest(error.A));
1045}
1046
1047test "result location initialization of error union with OPV payload" {
1048 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1049 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1051 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1052 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
1053
1054 const S = struct {
1055 x: u0,
1056 };
1057
1058 const a: anyerror!S = .{ .x = 0 };
1059 comptime assert((a catch unreachable).x == 0);
1060
1061 comptime {
1062 var b: anyerror!S = .{ .x = 0 };
1063 _ = &b;
1064 assert((b catch unreachable).x == 0);
1065 }
1066
1067 var c: anyerror!S = .{ .x = 0 };
1068 _ = &c;
1069 try expectEqual(0, (c catch return error.TestFailed).x);
1070}
1071
1072test "return error union with i65" {
1073 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1074 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1075
1076 try expect(try add(1000, 234) == 1234);
1077}
1078
1079fn add(x: i65, y: i65) anyerror!i65 {
1080 return x + y;
1081}
1082
1083test "compare error union to error set" {
1084 const S = struct {
1085 fn doTheTest(val: error{Foo}!i32) !void {
1086 if (error.Foo == val) return error.Unexpected;
1087 if (val == error.Foo) return error.Unexpected;
1088 }
1089 };
1090 try S.doTheTest(0);
1091 try comptime S.doTheTest(0);
1092}