1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const expect = std.testing.expect;
5
6test "try on error union" {
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8
9 try tryOnErrorUnionImpl();
10 try comptime tryOnErrorUnionImpl();
11}
12
13fn tryOnErrorUnionImpl() !void {
14 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
15 error.ItBroke, error.NoMem => 1,
16 error.CrappedOut => @as(i32, 2),
17 else => unreachable,
18 };
19 try expect(x == 11);
20}
21
22fn returnsTen() anyerror!i32 {
23 return 10;
24}
25
26test "try without vars" {
27 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
28 try expect(result1 == 2);
29
30 const result2 = if (failIfTrue(false)) 1 else |_| @as(i32, 2);
31 try expect(result2 == 1);
32}
33
34fn failIfTrue(ok: bool) anyerror!void {
35 if (ok) {
36 return error.ItBroke;
37 } else {
38 return;
39 }
40}
41
42test "try then not executed with assignment" {
43 if (failIfTrue(true)) {
44 unreachable;
45 } else |err| {
46 try expect(err == error.ItBroke);
47 }
48}
49
50test "`try`ing an if/else expression" {
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
54
55 const S = struct {
56 fn getError() !void {
57 return error.Test;
58 }
59
60 fn getError2() !void {
61 var a: u8 = 'c';
62 _ = &a;
63 try if (a == 'a') getError() else if (a == 'b') getError() else getError();
64 }
65 };
66
67 try std.testing.expectError(error.Test, S.getError2());
68}
69
70test "'return try' of empty error set in function returning non-error" {
71 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
73
74 const S = struct {
75 fn succeed0() error{}!u32 {
76 return 123;
77 }
78 fn succeed1() !u32 {
79 return 456;
80 }
81 fn tryNoError0() u32 {
82 return try succeed0();
83 }
84 fn tryNoError1() u32 {
85 return try succeed1();
86 }
87 fn tryNoError2() u32 {
88 const e: error{}!u32 = 789;
89 return try e;
90 }
91 fn doTheTest() !void {
92 const res0 = tryNoError0();
93 const res1 = tryNoError1();
94 const res2 = tryNoError2();
95 try expect(res0 == 123);
96 try expect(res1 == 456);
97 try expect(res2 == 789);
98 }
99 };
100 try S.doTheTest();
101 try comptime S.doTheTest();
102}
103
104test "'return try' through conditional" {
105 const S = struct {
106 fn get(t: bool) !u32 {
107 return try if (t) inner() else error.TestFailed;
108 }
109 fn inner() !u16 {
110 return 123;
111 }
112 };
113
114 {
115 const result = try S.get(true);
116 try expect(result == 123);
117 }
118
119 {
120 const result = try comptime S.get(true);
121 comptime std.debug.assert(result == 123);
122 }
123}
124
125test "try ptr propagation const" {
126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
130
131 const S = struct {
132 fn foo0() !u32 {
133 return 0;
134 }
135
136 fn foo1() error{Bad}!u32 {
137 return 1;
138 }
139
140 fn foo2() anyerror!u32 {
141 return 2;
142 }
143
144 fn doTheTest() !void {
145 const res0: *const u32 = &(try foo0());
146 const res1: *const u32 = &(try foo1());
147 const res2: *const u32 = &(try foo2());
148 try expect(res0.* == 0);
149 try expect(res1.* == 1);
150 try expect(res2.* == 2);
151 }
152 };
153 try S.doTheTest();
154 try comptime S.doTheTest();
155}
156
157test "try ptr propagation mutate" {
158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
159 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
162
163 const S = struct {
164 fn foo0() !u32 {
165 return 0;
166 }
167
168 fn foo1() error{Bad}!u32 {
169 return 1;
170 }
171
172 fn foo2() anyerror!u32 {
173 return 2;
174 }
175
176 fn doTheTest() !void {
177 var f0 = foo0();
178 var f1 = foo1();
179 var f2 = foo2();
180
181 const res0: *u32 = &(try f0);
182 const res1: *u32 = &(try f1);
183 const res2: *u32 = &(try f2);
184
185 res0.* += 1;
186 res1.* += 1;
187 res2.* += 1;
188
189 try expect(f0 catch unreachable == 1);
190 try expect(f1 catch unreachable == 2);
191 try expect(f2 catch unreachable == 3);
192
193 try expect(res0.* == 1);
194 try expect(res1.* == 2);
195 try expect(res2.* == 3);
196 }
197 };
198 try S.doTheTest();
199 try comptime S.doTheTest();
200}
201
202test "try pointer expression alignment" {
203 const S = struct {
204 fn doTheTest(p: *align(1) (anyerror!u32)) !void {
205 comptime assert(@TypeOf(&(try p.*)) == *align(1) u32);
206 try expect((try p.*) == 10);
207 }
208 };
209 var x: anyerror!u32 = 10;
210 try S.doTheTest(&x);
211}