authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-28 19:18:39+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-04-30 08:57:50+01:00
logd764716cb5cdcf3dec07d66ce87be915327f564e
treef38773a68062f1bb792405eb7e5a479777c2704b
parente67c344fc0ec62748cbfb645e14b9f99ad3655cd
signaturelock-open Commit is signed but in an unrecognized format.

compiler: remove capturing errdefer from the language

Resolves: https://github.com/ziglang/zig/issues/23734

13 files changed, 31 insertions(+), 267 deletions(-)

doc/langref.html.in+1-1
......@@ -7774,7 +7774,7 @@ ContainerField <- doc_comment? (KEYWORD_comptime / !KEYWORD_comptime) !KEYWORD_f
77747774BlockStatement
77757775 <- Statement
77767776 / KEYWORD_defer BlockExprStatement
7777 / KEYWORD_errdefer Payload? BlockExprStatement
7777 / KEYWORD_errdefer BlockExprStatement
77787778 / !ExprStatement (KEYWORD_comptime !BlockExpr)? VarAssignStatement
77797779
77807780Statement
lib/compiler/reduce/Walk.zig+1-5
......@@ -223,12 +223,8 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
223223 return walkBlock(w, node, statements);
224224 },
225225
226 .@"errdefer" => {
227 const expr = ast.nodeData(node).opt_token_and_node[1];
228 return walkExpression(w, expr);
229 },
230
231226 .@"defer",
227 .@"errdefer",
232228 .@"comptime",
233229 .@"nosuspend",
234230 .@"suspend",
lib/docs/wasm/Walk.zig+1-2
......@@ -1014,8 +1014,7 @@ fn block(
10141014
10151015 .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
10161016
1017 .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
1018 .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]),
1017 .@"defer", .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
10191018
10201019 else => try expr(w, scope, parent_decl, node),
10211020 }
lib/std/zig/Ast.zig+4-7
......@@ -952,8 +952,8 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
952952 .switch_range,
953953 => n = tree.nodeData(n).node_and_node[1],
954954
955 .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1],
956 .@"defer" => n = tree.nodeData(n).node,
955 .test_decl => n = tree.nodeData(n).opt_token_and_node[1],
956 .@"defer", .@"errdefer" => n = tree.nodeData(n).node,
957957 .anyframe_type => n = tree.nodeData(n).token_and_node[1],
958958
959959 .switch_case_one,
......@@ -3059,11 +3059,8 @@ pub const Node = struct {
30593059 /// a `assign_destructure` node or a parsing error occured.
30603060 aligned_var_decl,
30613061 /// `errdefer expr`,
3062 /// `errdefer |payload| expr`.
30633062 ///
3064 /// The `data` field is a `.opt_token_and_node`:
3065 /// 1. a `OptionalTokenIndex` to the payload identifier, if any.
3066 /// 2. a `Node.Index` to the deferred expression.
3063 /// The `data` field is a `.node` to the deferred expression.
30673064 ///
30683065 /// The `main_token` field is the `errdefer` token.
30693066 @"errdefer",
......@@ -3071,7 +3068,7 @@ pub const Node = struct {
30713068 ///
30723069 /// The `data` field is a `.node` to the deferred expression.
30733070 ///
3074 /// The `main_token` field is the `defer`.
3071 /// The `main_token` field is the `defer` token.
30753072 @"defer",
30763073 /// `lhs catch rhs`,
30773074 /// `lhs catch |err| rhs`.
lib/std/zig/Ast/Render.zig+1-13
......@@ -394,20 +394,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
394394 return renderBlock(r, node, statements, space);
395395 },
396396
397 .@"errdefer" => {
398 const defer_token = tree.nodeMainToken(node);
399 const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node;
400
401 try renderToken(r, defer_token, .maybe_space);
402 if (maybe_payload_token.unwrap()) |payload_token| {
403 try renderToken(r, payload_token - 1, .none); // |
404 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
405 try renderToken(r, payload_token + 1, .maybe_space); // |
406 }
407 return renderExpression(r, expr, space);
408 },
409
410397 .@"defer",
398 .@"errdefer",
411399 .@"comptime",
412400 .@"nosuspend",
413401 .@"suspend",
lib/std/zig/AstGen.zig+19-120
......@@ -2875,7 +2875,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
28752875 .max,
28762876 .min,
28772877 .@"resume",
2878 .ret_err_value_code,
28792878 .ret_ptr,
28802879 .ret_type,
28812880 .for_len,
......@@ -2964,7 +2963,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29642963 => break :b true,
29652964
29662965 .@"defer" => unreachable,
2967 .defer_err_code => unreachable,
29682966 }
29692967 } else switch (maybe_unused_result) {
29702968 .none => unreachable,
......@@ -2984,60 +2982,28 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29842982 return noreturn_src_node;
29852983}
29862984
2987fn countDefers(outer_scope: *Scope, inner_scope: *Scope) struct {
2988 have_any: bool,
2989 have_normal: bool,
2990 have_err: bool,
2991 need_err_code: bool,
2992} {
2993 var have_normal = false;
2994 var have_err = false;
2995 var need_err_code = false;
2985fn anyErrdefers(outer_scope: *Scope, inner_scope: *Scope) bool {
29962986 var scope = inner_scope;
29972987 while (scope != outer_scope) {
29982988 switch (scope.unwrap()) {
29992989 .gen_zir => |gen_zir| scope = gen_zir.parent,
30002990 .local_val => |local_val| scope = local_val.parent,
30012991 .local_ptr => |local_ptr| scope = local_ptr.parent,
3002 .defer_normal => |defer_scope| {
3003 scope = defer_scope.parent;
3004
3005 have_normal = true;
3006 },
3007 .defer_error => |defer_scope| {
3008 scope = defer_scope.parent;
3009
3010 have_err = true;
3011
3012 const have_err_payload = defer_scope.remapped_err_code != .none;
3013 need_err_code = need_err_code or have_err_payload;
3014 },
2992 .defer_normal => |defer_normal| scope = defer_normal.parent,
2993 .defer_error => return true,
30152994 .namespace => unreachable,
30162995 .top => unreachable,
30172996 }
30182997 }
3019 return .{
3020 .have_any = have_normal or have_err,
3021 .have_normal = have_normal,
3022 .have_err = have_err,
3023 .need_err_code = need_err_code,
3024 };
2998 return false;
30252999}
30263000
3027const DefersToEmit = union(enum) {
3028 both: Zir.Inst.Ref, // err code
3029 both_sans_err,
3030 normal_only,
3031};
3032
30333001fn genDefers(
30343002 gz: *GenZir,
30353003 outer_scope: *Scope,
30363004 inner_scope: *Scope,
3037 which_ones: DefersToEmit,
3005 which_ones: enum { normal_only, normal_and_error },
30383006) InnerError!void {
3039 const gpa = gz.astgen.gpa;
3040
30413007 var scope = inner_scope;
30423008 while (scope != outer_scope) {
30433009 switch (scope.unwrap()) {
......@@ -3051,33 +3017,10 @@ fn genDefers(
30513017 .defer_error => |defer_scope| {
30523018 scope = defer_scope.parent;
30533019 switch (which_ones) {
3054 .both_sans_err => {
3020 .normal_only => continue,
3021 .normal_and_error => {
30553022 try gz.addDefer(defer_scope.index, defer_scope.len);
30563023 },
3057 .both => |err_code| {
3058 if (defer_scope.remapped_err_code.unwrap()) |remapped_err_code| {
3059 try gz.instructions.ensureUnusedCapacity(gpa, 1);
3060 try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1);
3061
3062 const payload_index = try gz.astgen.addExtra(Zir.Inst.DeferErrCode{
3063 .remapped_err_code = remapped_err_code,
3064 .index = defer_scope.index,
3065 .len = defer_scope.len,
3066 });
3067 const new_index: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
3068 gz.astgen.instructions.appendAssumeCapacity(.{
3069 .tag = .defer_err_code,
3070 .data = .{ .defer_err_code = .{
3071 .err_code = err_code,
3072 .payload_index = payload_index,
3073 } },
3074 });
3075 gz.instructions.appendAssumeCapacity(new_index);
3076 } else {
3077 try gz.addDefer(defer_scope.index, defer_scope.len);
3078 }
3079 },
3080 .normal_only => continue,
30813024 }
30823025 },
30833026 .namespace => unreachable,
......@@ -3140,46 +3083,17 @@ fn deferStmt(
31403083 defer defer_gen.unstack();
31413084
31423085 const tree = gz.astgen.tree;
3143 var local_val_scope: Scope.LocalVal = undefined;
3144 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3145 const sub_scope = if (scope_tag != .defer_error) &defer_gen.base else blk: {
3146 const payload_token = tree.nodeData(node).opt_token_and_node[0].unwrap() orelse break :blk &defer_gen.base;
3147 const ident_name = try gz.astgen.identAsString(payload_token);
3148 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {
3149 try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{});
3150 break :blk &defer_gen.base;
3151 }
3152 const remapped_err_code: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len);
3153 opt_remapped_err_code = remapped_err_code.toOptional();
3154 _ = try gz.astgen.appendPlaceholder();
3155 const remapped_err_code_ref = remapped_err_code.toRef();
3156 local_val_scope = .{
3157 .parent = &defer_gen.base,
3158 .gen_zir = gz,
3159 .name = ident_name,
3160 .inst = remapped_err_code_ref,
3161 .token_src = payload_token,
3162 .id_cat = .capture,
3163 };
3164 try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref);
3165 break :blk &local_val_scope.base;
3166 };
3167 const expr_node = switch (scope_tag) {
3168 .defer_normal => tree.nodeData(node).node,
3169 .defer_error => tree.nodeData(node).opt_token_and_node[1],
3170 else => unreachable,
3171 };
3172 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
3173 try checkUsed(gz, scope, sub_scope);
3086 const expr_node = tree.nodeData(node).node;
3087 _ = try unusedResultExpr(&defer_gen, &defer_gen.base, expr_node);
3088 try checkUsed(gz, scope, &defer_gen.base);
31743089 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
31753090
31763091 const body = defer_gen.instructionsSlice();
3177 const extra_insts: []const Zir.Inst.Index = if (opt_remapped_err_code.unwrap()) |ec| &.{ec} else &.{};
3178 const body_len = gz.astgen.countBodyLenAfterFixupsExtraRefs(body, extra_insts);
3092 const body_len = gz.astgen.countBodyLenAfterFixupsExtraRefs(body, &.{});
31793093
31803094 const index: u32 = @intCast(gz.astgen.extra.items.len);
31813095 try gz.astgen.extra.ensureUnusedCapacity(gz.astgen.gpa, body_len);
3182 gz.astgen.appendBodyWithFixupsExtraRefsArrayList(&gz.astgen.extra, body, extra_insts);
3096 gz.astgen.appendBodyWithFixupsExtraRefsArrayList(&gz.astgen.extra, body, &.{});
31833097
31843098 const defer_scope = try block_arena.create(Scope.Defer);
31853099
......@@ -3188,7 +3102,6 @@ fn deferStmt(
31883102 .parent = scope,
31893103 .index = index,
31903104 .len = body_len,
3191 .remapped_err_code = opt_remapped_err_code,
31923105 };
31933106 return &defer_scope.base;
31943107}
......@@ -5882,7 +5795,7 @@ fn tryExpr(
58825795 else => Zir.Inst.Tag.err_union_code,
58835796 };
58845797 const err_code = try else_scope.addUnNode(err_tag, operand, node);
5885 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
5798 try genDefers(&else_scope, &fn_block.base, scope, .normal_and_error);
58865799 try emitDbgStmt(&else_scope, try_lc);
58875800 _ = try else_scope.addUnNode(.ret_node, err_code, node);
58885801
......@@ -8033,18 +7946,10 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
80337946 // for detecting whether to add something to the function's inferred error set.
80347947 const ident_token = tree.nodeMainToken(operand_node) + 2;
80357948 const err_name_str_index = try astgen.identAsString(ident_token);
8036 const defer_counts = countDefers(defer_outer, scope);
8037 if (!defer_counts.need_err_code) {
8038 try genDefers(gz, defer_outer, scope, .both_sans_err);
8039 try emitDbgStmt(gz, ret_lc);
8040 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
8041 return Zir.Inst.Ref.unreachable_value;
8042 }
8043 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
8044 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7949 try genDefers(gz, defer_outer, scope, .normal_and_error);
80457950 try emitDbgStmt(gz, ret_lc);
8046 _ = try gz.addUnNode(.ret_node, err_code, node);
8047 return Zir.Inst.Ref.unreachable_value;
7951 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
7952 return .unreachable_value;
80487953 }
80497954
80507955 const ri: ResultInfo = if (astgen.nodes_need_rl.contains(node)) .{
......@@ -8071,15 +7976,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
80717976 },
80727977 .always => {
80737978 // Value is always an error. Emit both error defers and regular defers.
8074 const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
8075 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7979 try genDefers(gz, defer_outer, scope, .normal_and_error);
80767980 try emitDbgStmt(gz, ret_lc);
80777981 try gz.addRet(ri, operand, node);
80787982 return Zir.Inst.Ref.unreachable_value;
80797983 },
80807984 .maybe => {
8081 const defer_counts = countDefers(defer_outer, scope);
8082 if (!defer_counts.have_err) {
7985 if (!anyErrdefers(defer_outer, scope)) {
80837986 // Only regular defers; no branch needed.
80847987 try genDefers(gz, defer_outer, scope, .normal_only);
80857988 try emitDbgStmt(gz, ret_lc);
......@@ -8111,10 +8014,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
81118014 var else_scope = gz.makeSubBlock(scope);
81128015 defer else_scope.unstack();
81138016
8114 const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{
8115 .both = try else_scope.addUnNode(.err_union_code, result, node),
8116 };
8117 try genDefers(&else_scope, defer_outer, scope, which_ones);
8017 try genDefers(&else_scope, defer_outer, scope, .normal_and_error);
81188018 try emitDbgStmt(&else_scope, ret_lc);
81198019 try else_scope.addRet(ri, operand, node);
81208020
......@@ -11239,7 +11139,6 @@ const Scope = struct {
1123911139 parent: *Scope,
1124011140 index: u32,
1124111141 len: u32,
11242 remapped_err_code: Zir.Inst.OptionalIndex = .none,
1124311142 };
1124411143
1124511144 /// Represents a global scope that has any number of declarations in it.
lib/std/zig/AstRlAnnotate.zig+1-5
......@@ -141,11 +141,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
141141 .asm_input,
142142 => unreachable,
143143
144 .@"errdefer" => {
145 _ = try astrl.expr(tree.nodeData(node).opt_token_and_node[1], block, ResultInfo.none);
146 return false;
147 },
148 .@"defer" => {
144 .@"defer", .@"errdefer" => {
149145 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
150146 return false;
151147 },
lib/std/zig/AstSmith.zig+1-1
......@@ -486,7 +486,7 @@ fn pegContainerField(a: *AstSmith) SourceError!void {
486486/// BlockStatement
487487/// <- Statement
488488/// / KEYWORD_defer BlockExprStatement
489/// / KEYWORD_errdefer Payload? BlockExprStatement
489/// / KEYWORD_errdefer BlockExprStatement
490490/// / !ExprStatement (KEYWORD_comptime !BlockExpr)? VarAssignStatement
491491fn pegBlockStatement(a: *AstSmith) SourceError!void {
492492 const Kind = enum {
lib/std/zig/Parse.zig+2-5
......@@ -909,7 +909,7 @@ fn expectContainerField(p: *Parse) !Node.Index {
909909/// BlockStatement
910910/// <- Statement
911911/// / KEYWORD_defer BlockExprStatement
912/// / KEYWORD_errdefer Payload? BlockExprStatement
912/// / KEYWORD_errdefer BlockExprStatement
913913/// / !ExprStatement (KEYWORD_comptime !BlockExpr)? VarAssignStatement
914914///
915915/// Statement
......@@ -975,10 +975,7 @@ fn expectStatement(p: *Parse, is_block_level: bool) Error!Node.Index {
975975 .keyword_errdefer => if (is_block_level) return p.addNode(.{
976976 .tag = .@"errdefer",
977977 .main_token = p.nextToken(),
978 .data = .{ .opt_token_and_node = .{
979 try p.parsePayload(),
980 try p.expectBlockExprStatement(),
981 } },
978 .data = .{ .node = try p.expectBlockExprStatement() },
982979 }),
983980 .keyword_if => return p.expectIfStatement(),
984981 .keyword_enum, .keyword_struct, .keyword_union => {
lib/std/zig/Zir.zig-37
......@@ -597,13 +597,6 @@ pub const Inst = struct {
597597 /// name is added to it.
598598 /// Uses the `str_tok` union field.
599599 ret_err_value,
600 /// A string name is provided which is an anonymous error set value.
601 /// If the current function has an inferred error set, the error given by the
602 /// name is added to it.
603 /// Results in the error code. Note that control flow is not diverted with
604 /// this instruction; a following 'ret' instruction will do the diversion.
605 /// Uses the `str_tok` union field.
606 ret_err_value_code,
607600 /// Obtains a pointer to the return value.
608601 /// Uses the `node` union field.
609602 ret_ptr,
......@@ -1066,9 +1059,6 @@ pub const Inst = struct {
10661059 /// A defer statement.
10671060 /// Uses the `defer` union field.
10681061 @"defer",
1069 /// An errdefer statement with a code.
1070 /// Uses the `err_defer_code` union field.
1071 defer_err_code,
10721062
10731063 /// Requests that Sema update the saved error return trace index for the enclosing
10741064 /// block, if the operand is .none or of an error/error-union type.
......@@ -1295,14 +1285,12 @@ pub const Inst = struct {
12951285 .memmove,
12961286 .min,
12971287 .@"resume",
1298 .ret_err_value_code,
12991288 .extended,
13001289 .ret_ptr,
13011290 .ret_type,
13021291 .@"try",
13031292 .try_ptr,
13041293 .@"defer",
1305 .defer_err_code,
13061294 .save_err_ret_index,
13071295 .for_len,
13081296 .opt_eu_base_ptr_init,
......@@ -1377,7 +1365,6 @@ pub const Inst = struct {
13771365 .memmove,
13781366 .check_comptime_control_flow,
13791367 .@"defer",
1380 .defer_err_code,
13811368 .save_err_ret_index,
13821369 .restore_err_ret_index_unconditional,
13831370 .restore_err_ret_index_fn_entry,
......@@ -1574,7 +1561,6 @@ pub const Inst = struct {
15741561 .max,
15751562 .min,
15761563 .@"resume",
1577 .ret_err_value_code,
15781564 .@"break",
15791565 .break_inline,
15801566 .condbr,
......@@ -1732,7 +1718,6 @@ pub const Inst = struct {
17321718 .ret_load = .un_node,
17331719 .ret_implicit = .un_tok,
17341720 .ret_err_value = .str_tok,
1735 .ret_err_value_code = .str_tok,
17361721 .ret_ptr = .node,
17371722 .ret_type = .node,
17381723 .ptr_type = .ptr_type,
......@@ -1866,7 +1851,6 @@ pub const Inst = struct {
18661851 .@"resume" = .un_node,
18671852
18681853 .@"defer" = .@"defer",
1869 .defer_err_code = .defer_err_code,
18701854
18711855 .save_err_ret_index = .save_err_ret_index,
18721856 .restore_err_ret_index_unconditional = .un_node,
......@@ -2484,10 +2468,6 @@ pub const Inst = struct {
24842468 index: u32,
24852469 len: u32,
24862470 },
2487 defer_err_code: struct {
2488 err_code: Ref,
2489 payload_index: u32,
2490 },
24912471 save_err_ret_index: struct {
24922472 operand: Ref, // If error type (or .none), save new trace index
24932473 },
......@@ -2538,7 +2518,6 @@ pub const Inst = struct {
25382518 inst_node,
25392519 str_op,
25402520 @"defer",
2541 defer_err_code,
25422521 save_err_ret_index,
25432522 elem_val_imm,
25442523 declaration,
......@@ -3974,12 +3953,6 @@ pub const Inst = struct {
39743953 column: u32,
39753954 };
39763955
3977 pub const DeferErrCode = struct {
3978 remapped_err_code: Index,
3979 index: u32,
3980 len: u32,
3981 };
3982
39833956 pub const ValidateDestructure = struct {
39843957 /// The value being destructured.
39853958 operand: Ref,
......@@ -4222,7 +4195,6 @@ fn findTrackableInner(
42224195 .ret_load,
42234196 .ret_implicit,
42244197 .ret_err_value,
4225 .ret_err_value_code,
42264198 .ret_ptr,
42274199 .ret_type,
42284200 .ptr_type,
......@@ -4621,15 +4593,6 @@ fn findTrackableInner(
46214593 try zir.findTrackableBody(gpa, contents, defers, body);
46224594 }
46234595 },
4624 .defer_err_code => {
4625 const inst_data = datas[@intFromEnum(inst)].defer_err_code;
4626 const extra = zir.extraData(Inst.DeferErrCode, inst_data.payload_index).data;
4627 const gop = try defers.getOrPut(gpa, extra.index);
4628 if (!gop.found_existing) {
4629 const body = zir.bodySlice(extra.index, extra.len);
4630 try zir.findTrackableBody(gpa, contents, defers, body);
4631 }
4632 },
46334596 }
46344597}
46354598
lib/std/zig/parser_test.zig-13
......@@ -298,19 +298,6 @@ test "zig fmt: decl between fields" {
298298 });
299299}
300300
301test "zig fmt: errdefer with payload" {
302 try testCanonical(
303 \\pub fn main() anyerror!void {
304 \\ errdefer |a| x += 1;
305 \\ errdefer |a| {}
306 \\ errdefer |a| {
307 \\ x += 1;
308 \\ }
309 \\}
310 \\
311 );
312}
313
314301test "zig fmt: nosuspend block" {
315302 try testCanonical(
316303 \\pub fn main() anyerror!void {
src/Sema.zig-43
......@@ -1245,7 +1245,6 @@ fn analyzeBodyInner(
12451245 .optional_type => try sema.zirOptionalType(block, inst),
12461246 .ptr_type => try sema.zirPtrType(block, inst),
12471247 .ref => try sema.zirRef(block, inst),
1248 .ret_err_value_code => try sema.zirRetErrValueCode(inst),
12491248 .shr => try sema.zirShr(block, inst, .shr),
12501249 .shr_exact => try sema.zirShr(block, inst, .shr_exact),
12511250 .slice_end => try sema.zirSliceEnd(block, inst),
......@@ -1969,25 +1968,6 @@ fn analyzeBodyInner(
19691968 }
19701969 break :blk .void_value;
19711970 },
1972 .defer_err_code => blk: {
1973 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;
1974 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
1975 const defer_body = sema.code.bodySlice(extra.index, extra.len);
1976 const err_code = sema.resolveInst(inst_data.err_code);
1977 try map.ensureSpaceForInstructions(sema.gpa, defer_body);
1978 map.putAssumeCapacity(extra.remapped_err_code, err_code);
1979 if (sema.analyzeBodyInner(block, defer_body)) {
1980 // The defer terminated noreturn - no more analysis needed.
1981 break;
1982 } else |err| switch (err) {
1983 error.ComptimeBreak => {},
1984 else => |e| return e,
1985 }
1986 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) {
1987 return error.ComptimeBreak;
1988 }
1989 break :blk .void_value;
1990 },
19911971 };
19921972
19931973 const is_inferred_alloc = if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst)]) {
......@@ -12938,29 +12918,6 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1293812918 return Air.internedToRef(result.val);
1293912919}
1294012920
12941fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12942 const pt = sema.pt;
12943 const zcu = pt.zcu;
12944 const comp = zcu.comp;
12945 const gpa = comp.gpa;
12946 const io = comp.io;
12947
12948 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
12949 const name = try zcu.intern_pool.getOrPutString(
12950 gpa,
12951 io,
12952 pt.tid,
12953 inst_data.get(sema.code),
12954 .no_embedded_nulls,
12955 );
12956 _ = try pt.getErrorValue(name);
12957 const error_set_type = try pt.singleErrorSetType(name);
12958 return Air.internedToRef((try pt.intern(.{ .err = .{
12959 .ty = error_set_type.toIntern(),
12960 .name = name,
12961 } })));
12962}
12963
1296412921fn zirShl(
1296512922 sema: *Sema,
1296612923 block: *Block,
src/print_zir.zig-15
......@@ -477,7 +477,6 @@ const Writer = struct {
477477 .decl_ref,
478478 .decl_val,
479479 .ret_err_value,
480 .ret_err_value_code,
481480 .param_anytype,
482481 .param_anytype_comptime,
483482 => try self.writeStrTok(stream, inst),
......@@ -497,7 +496,6 @@ const Writer = struct {
497496 .dbg_stmt => try self.writeDbgStmt(stream, inst),
498497
499498 .@"defer" => try self.writeDefer(stream, inst),
500 .defer_err_code => try self.writeDeferErrCode(stream, inst),
501499
502500 .declaration => try self.writeDeclaration(stream, inst),
503501
......@@ -2186,19 +2184,6 @@ const Writer = struct {
21862184 try stream.writeByte(')');
21872185 }
21882186
2189 fn writeDeferErrCode(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
2190 const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code;
2191 const extra = self.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
2192
2193 try self.writeInstRef(stream, extra.remapped_err_code.toRef());
2194 try stream.writeAll(" = ");
2195 try self.writeInstRef(stream, inst_data.err_code);
2196 try stream.writeAll(", ");
2197 const body = self.code.bodySlice(extra.index, extra.len);
2198 try self.writeBracedBody(stream, body);
2199 try stream.writeByte(')');
2200 }
2201
22022187 fn writeDeclaration(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void {
22032188 const decl = self.code.getDeclaration(inst);
22042189