authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2024-09-03 14:37:15-04:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2024-09-03 22:56:23+01:00
log7a4d69983a6ac7ab91f71910cec5886ed5bec745
tree085a161cf0a257ff15b9b86e89865f300286247d
parent242d268a06261d31161ad3a30ac0c2827ca49d99

AstGen: update @errorCast to maybe eval to err

Consequently, `AstGen.ret()` now passes the error code to `.defer_error_code`. Previously, the error union value was passed. closes #20371

2 files changed, 38 insertions(+), 1 deletions(-)

lib/std/zig/BuiltinFn.zig+1-1
......@@ -482,7 +482,7 @@ pub const list = list: {
482482 "@errorCast",
483483 .{
484484 .tag = .error_cast,
485 .eval_to_error = .always,
485 .eval_to_error = .maybe,
486486 .param_count = 1,
487487 },
488488 },
test/behavior/defer.zig+37
......@@ -197,3 +197,40 @@ const defer_assign = switch (block: {
197197comptime {
198198 if (defer_assign != 0) @compileError("defer_assign failed!");
199199}
200
201test "errdefer capture" {
202 const S = struct {
203 fail: bool = undefined,
204 fn bar0(self: *@This()) error{a}!void {
205 self.fail = false;
206 errdefer |err| if (@TypeOf(err) != error{a}) {
207 self.fail = true;
208 };
209 return error.a;
210 }
211 fn bar1(self: *@This()) error{a}!void {
212 self.fail = false;
213 errdefer |err| if (@TypeOf(err) != error{a}) {
214 self.fail = true;
215 };
216 const rv: error{a}!void = @errorCast(@as(error{a}!void, error.a));
217 return rv;
218 }
219 // https://github.com/ziglang/zig/issues/20371
220 fn bar2(self: *@This()) error{a}!void {
221 self.fail = false;
222 errdefer |err| if (@TypeOf(err) != error{a}) {
223 self.fail = true;
224 };
225 return @errorCast(@as(error{a}!void, error.a));
226 }
227 };
228
229 var s: S = .{};
230 s.bar0() catch {};
231 if (s.fail) return error.TestExpectedError;
232 s.bar1() catch {};
233 if (s.fail) return error.TestExpectedError;
234 s.bar2() catch {};
235 if (s.fail) return error.TestExpectedError;
236}