authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-28 13:06:32+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-29 23:27:58+01:00
loge67c344fc0ec62748cbfb645e14b9f99ad3655cd
tree40e26446bfd6a2fa4d2b8e8d2730347472378fc0
parent7b44e8986fa0a8121993ab328b129789127a13bd
signaturelock-open Commit is signed but in an unrecognized format.

compiler,tests,tools: remove uses of capturing errdefer

In preparation for its removal, as accepted in https://github.com/ziglang/zig/issues/23734.

5 files changed, 15 insertions(+), 113 deletions(-)

src/codegen/aarch64/Select.zig+5-3
......@@ -11222,14 +11222,16 @@ fn initValueAdvanced(
1122211222 };
1122311223 return @enumFromInt(isel.values.items.len);
1122411224}
11225pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {
11225const WhichValues = enum { only_referenced, all };
11226pub fn dumpValues(isel: *Select, which: WhichValues) void {
11227 dumpValuesInner(isel, which) catch |err| @panic(@errorName(err));
11228}
11229fn dumpValuesInner(isel: *Select, which: WhichValues) !void {
1122611230 const zcu = isel.pt.zcu;
1122711231 const gpa = zcu.gpa;
1122811232 const ip = &zcu.intern_pool;
1122911233 const nav = ip.getNav(isel.nav_index);
1123011234
11231 errdefer |err| @panic(@errorName(err));
11232
1123311235 const locked_stderr = std.debug.lockStderr(&.{});
1123411236 defer std.debug.unlockStderr();
1123511237 const stderr = &locked_stderr.file_writer.interface;
test/behavior/defer.zig+1-85
......@@ -106,51 +106,6 @@ test "mixing normal and error defers" {
106106 try expect(result[2] == 'a');
107107}
108108
109test "errdefer with payload" {
110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
114
115 const S = struct {
116 fn foo() !i32 {
117 errdefer |a| {
118 expectEqual(error.One, a) catch @panic("test failure");
119 }
120 return error.One;
121 }
122 fn doTheTest() !void {
123 try expectError(error.One, foo());
124 }
125 };
126 try S.doTheTest();
127 try comptime S.doTheTest();
128}
129
130test "reference to errdefer payload" {
131 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
135
136 const S = struct {
137 fn foo() !i32 {
138 errdefer |a| {
139 const ptr = &a;
140 const ptr2 = &ptr;
141 expectEqual(error.One, ptr2.*.*) catch @panic("test failure");
142 expectEqual(error.One, ptr.*) catch @panic("test failure");
143 }
144 return error.One;
145 }
146 fn doTheTest() !void {
147 try expectError(error.One, foo());
148 }
149 };
150 try S.doTheTest();
151 try comptime S.doTheTest();
152}
153
154109test "simple else prong doesn't emit an error for unreachable else prong" {
155110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
156111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -192,47 +147,8 @@ comptime {
192147 if (defer_assign != 0) @compileError("defer_assign failed!");
193148}
194149
195test "errdefer capture" {
196 const S = struct {
197 fail: bool = undefined,
198 fn bar0(self: *@This()) error{a}!void {
199 self.fail = false;
200 errdefer |err| if (@TypeOf(err) != error{a}) {
201 self.fail = true;
202 };
203 return error.a;
204 }
205 fn bar1(self: *@This()) error{a}!void {
206 self.fail = false;
207 errdefer |err| if (@TypeOf(err) != error{a}) {
208 self.fail = true;
209 };
210 const rv: error{a}!void = @errorCast(@as(error{a}!void, error.a));
211 return rv;
212 }
213 // https://github.com/ziglang/zig/issues/20371
214 fn bar2(self: *@This()) error{a}!void {
215 self.fail = false;
216 errdefer |err| if (@TypeOf(err) != error{a}) {
217 self.fail = true;
218 };
219 return @errorCast(@as(error{a}!void, error.a));
220 }
221 };
222
223 var s: S = .{};
224 s.bar0() catch {};
225 if (s.fail) return error.TestExpectedError;
226 s.bar1() catch {};
227 if (s.fail) return error.TestExpectedError;
228 s.bar2() catch {};
229 if (s.fail) return error.TestExpectedError;
230}
231
232150test "errdefer in test block" {
233 errdefer |err| {
234 _ = &err;
235 }
151 errdefer {}
236152 var x: bool = false;
237153 _ = &x;
238154 if (x) return error.Something;
test/cases/compile_errors/invalid_error_capture_discard.zig+6-13
......@@ -1,28 +1,21 @@
11export fn a() void {
2 errdefer |_| {
3 @"_";
4 }
5}
6export fn b() void {
72 const x: error{}!void = {};
83 x catch |_| {
94 @"_";
105 };
116}
12export fn c() void {
7export fn b() void {
138 const x: error{}!void = {};
149 x catch |_| switch (_) {};
1510}
16export fn d() void {
11export fn c() void {
1712 const x: error{}!u32 = 0;
1813 if (x) |v| v else |_| switch (_) {}
1914}
2015
2116// error
2217//
23// :2:15: error: discard of error capture; omit it instead
24// :3:9: error: use of undeclared identifier '_'
25// :8:14: error: discard of error capture; omit it instead
26// :9:9: error: use of undeclared identifier '_'
27// :14:14: error: discard of error capture; omit it instead
28// :18:24: error: discard of error capture; omit it instead
18// :3:14: error: discard of error capture; omit it instead
19// :4:9: error: use of undeclared identifier '_'
20// :9:14: error: discard of error capture; omit it instead
21// :13:24: error: discard of error capture; omit it instead
test/cases/compile_errors/unused_variable_error_on_errdefer.zig deleted-11
......@@ -1,11 +0,0 @@
1fn foo() !void {
2 errdefer |a| unreachable;
3 return error.A;
4}
5export fn entry() void {
6 foo() catch unreachable;
7}
8
9// error
10//
11// :2:15: error: unused capture
tools/update_cpu_features.zig+3-1
......@@ -2010,7 +2010,9 @@ const Job = struct {
20102010};
20112011
20122012fn processOneTarget(io: Io, job: Job) void {
2013 errdefer |err| std.debug.panic("panic: {s}", .{@errorName(err)});
2013 processOneTargetInner(io, job) catch |err| std.debug.panic("panic: {s}", .{@errorName(err)});
2014}
2015fn processOneTargetInner(io: Io, job: Job) !void {
20142016 const target = job.target;
20152017
20162018 var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);