authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-06 19:03:40+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-01-10 19:17:42+02:00
log83673a8b5f508376c81deaa4b01815474873eb69
treeccfd27379ec2bb5af7e57ce188350f3831856e04
parentfd6b79e67f0cf91a72c121fc6fd484a03f487506

fix errdefers in functions that can't return errors

This was broken by 58caed1c71179f48c4e7bffadef0392fa8381e72 Closes #14053

5 files changed, 33 insertions(+), 2 deletions(-)

src/AstGen.zig+2-1
......@@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
24632463 .is_non_null_ptr,
24642464 .is_non_err,
24652465 .is_non_err_ptr,
2466 .ret_is_non_err,
24662467 .mod_rem,
24672468 .mul,
24682469 .mulwrap,
......@@ -7012,7 +7013,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
70127013
70137014 // Emit conditional branch for generating errdefers.
70147015 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
7015 const is_non_err = try gz.addUnNode(.is_non_err, result, node);
7016 const is_non_err = try gz.addUnNode(.ret_is_non_err, result, node);
70167017 const condbr = try gz.addCondBr(.condbr, node);
70177018
70187019 var then_scope = gz.makeSubBlock(scope);
src/Sema.zig+13-1
......@@ -953,6 +953,7 @@ fn analyzeBodyInner(
953953 .int_type => try sema.zirIntType(block, inst),
954954 .is_non_err => try sema.zirIsNonErr(block, inst),
955955 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
956 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
956957 .is_non_null => try sema.zirIsNonNull(block, inst),
957958 .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),
958959 .merge_error_sets => try sema.zirMergeErrorSets(block, inst),
......@@ -10288,6 +10289,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1028810289 .ret_err_value_code,
1028910290 .restore_err_ret_index,
1029010291 .is_non_err,
10292 .ret_is_non_err,
1029110293 .condbr,
1029210294 => {},
1029310295 else => break,
......@@ -16577,7 +16579,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1657716579 const src = inst_data.src();
1657816580 const operand = try sema.resolveInst(inst_data.operand);
1657916581 try sema.checkErrorType(block, src, sema.typeOf(operand));
16580 return sema.analyzeIsNonErr(block, inst_data.src(), operand);
16582 return sema.analyzeIsNonErr(block, src, operand);
1658116583}
1658216584
1658316585fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -16592,6 +16594,16 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1659216594 return sema.analyzeIsNonErr(block, src, loaded);
1659316595}
1659416596
16597fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16598 const tracy = trace(@src());
16599 defer tracy.end();
16600
16601 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
16602 const src = inst_data.src();
16603 const operand = try sema.resolveInst(inst_data.operand);
16604 return sema.analyzeIsNonErr(block, src, operand);
16605}
16606
1659516607fn zirCondbr(
1659616608 sema: *Sema,
1659716609 parent_block: *Block,
src/Zir.zig+6
......@@ -481,6 +481,9 @@ pub const Inst = struct {
481481 /// Return a boolean false if dereferenced pointer is an error
482482 /// Uses the `un_node` field.
483483 is_non_err_ptr,
484 /// Same as `is_non_er` but doesn't validate that the type can be an error.
485 /// Uses the `un_node` field.
486 ret_is_non_err,
484487 /// A labeled block of code that loops forever. At the end of the body will have either
485488 /// a `repeat` instruction or a `repeat_inline` instruction.
486489 /// Uses the `pl_node` field. The AST node is either a for loop or while loop.
......@@ -1083,6 +1086,7 @@ pub const Inst = struct {
10831086 .is_non_null_ptr,
10841087 .is_non_err,
10851088 .is_non_err_ptr,
1089 .ret_is_non_err,
10861090 .mod_rem,
10871091 .mul,
10881092 .mulwrap,
......@@ -1386,6 +1390,7 @@ pub const Inst = struct {
13861390 .is_non_null_ptr,
13871391 .is_non_err,
13881392 .is_non_err_ptr,
1393 .ret_is_non_err,
13891394 .mod_rem,
13901395 .mul,
13911396 .mulwrap,
......@@ -1640,6 +1645,7 @@ pub const Inst = struct {
16401645 .is_non_null_ptr = .un_node,
16411646 .is_non_err = .un_node,
16421647 .is_non_err_ptr = .un_node,
1648 .ret_is_non_err = .un_node,
16431649 .loop = .pl_node,
16441650 .repeat = .node,
16451651 .repeat_inline = .node,
src/print_zir.zig+1
......@@ -179,6 +179,7 @@ const Writer = struct {
179179 .is_non_null_ptr,
180180 .is_non_err,
181181 .is_non_err_ptr,
182 .ret_is_non_err,
182183 .typeof,
183184 .struct_init_empty,
184185 .type_info,
test/behavior/defer.zig+11
......@@ -148,3 +148,14 @@ test "simple else prong doesn't emit an error for unreachable else prong" {
148148 };
149149 try expect(a == 1);
150150}
151
152test "errdefer used in function that doesn't return an error" {
153 const S = struct {
154 fn foo() u8 {
155 var a: u8 = 5;
156 errdefer a += 1;
157 return a;
158 }
159 };
160 try expect(S.foo() == 5);
161}