mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
fix errdefers in functions that can't return errors
This was broken by 58caed1c71179f48c4e7bffadef0392fa8381e72 Closes #14053
This commit is contained in:
parent
fd6b79e67f
commit
83673a8b5f
@ -2463,6 +2463,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.is_non_null_ptr,
|
||||
.is_non_err,
|
||||
.is_non_err_ptr,
|
||||
.ret_is_non_err,
|
||||
.mod_rem,
|
||||
.mul,
|
||||
.mulwrap,
|
||||
@ -7012,7 +7013,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||
|
||||
// Emit conditional branch for generating errdefers.
|
||||
const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
|
||||
const is_non_err = try gz.addUnNode(.is_non_err, result, node);
|
||||
const is_non_err = try gz.addUnNode(.ret_is_non_err, result, node);
|
||||
const condbr = try gz.addCondBr(.condbr, node);
|
||||
|
||||
var then_scope = gz.makeSubBlock(scope);
|
||||
|
||||
14
src/Sema.zig
14
src/Sema.zig
@ -953,6 +953,7 @@ fn analyzeBodyInner(
|
||||
.int_type => try sema.zirIntType(block, inst),
|
||||
.is_non_err => try sema.zirIsNonErr(block, inst),
|
||||
.is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
|
||||
.ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
|
||||
.is_non_null => try sema.zirIsNonNull(block, inst),
|
||||
.is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst),
|
||||
.merge_error_sets => try sema.zirMergeErrorSets(block, inst),
|
||||
@ -10288,6 +10289,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||
.ret_err_value_code,
|
||||
.restore_err_ret_index,
|
||||
.is_non_err,
|
||||
.ret_is_non_err,
|
||||
.condbr,
|
||||
=> {},
|
||||
else => break,
|
||||
@ -16577,7 +16579,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
const src = inst_data.src();
|
||||
const operand = try sema.resolveInst(inst_data.operand);
|
||||
try sema.checkErrorType(block, src, sema.typeOf(operand));
|
||||
return sema.analyzeIsNonErr(block, inst_data.src(), operand);
|
||||
return sema.analyzeIsNonErr(block, src, operand);
|
||||
}
|
||||
|
||||
fn 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
|
||||
return sema.analyzeIsNonErr(block, src, loaded);
|
||||
}
|
||||
|
||||
fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const operand = try sema.resolveInst(inst_data.operand);
|
||||
return sema.analyzeIsNonErr(block, src, operand);
|
||||
}
|
||||
|
||||
fn zirCondbr(
|
||||
sema: *Sema,
|
||||
parent_block: *Block,
|
||||
|
||||
@ -481,6 +481,9 @@ pub const Inst = struct {
|
||||
/// Return a boolean false if dereferenced pointer is an error
|
||||
/// Uses the `un_node` field.
|
||||
is_non_err_ptr,
|
||||
/// Same as `is_non_er` but doesn't validate that the type can be an error.
|
||||
/// Uses the `un_node` field.
|
||||
ret_is_non_err,
|
||||
/// A labeled block of code that loops forever. At the end of the body will have either
|
||||
/// a `repeat` instruction or a `repeat_inline` instruction.
|
||||
/// Uses the `pl_node` field. The AST node is either a for loop or while loop.
|
||||
@ -1083,6 +1086,7 @@ pub const Inst = struct {
|
||||
.is_non_null_ptr,
|
||||
.is_non_err,
|
||||
.is_non_err_ptr,
|
||||
.ret_is_non_err,
|
||||
.mod_rem,
|
||||
.mul,
|
||||
.mulwrap,
|
||||
@ -1386,6 +1390,7 @@ pub const Inst = struct {
|
||||
.is_non_null_ptr,
|
||||
.is_non_err,
|
||||
.is_non_err_ptr,
|
||||
.ret_is_non_err,
|
||||
.mod_rem,
|
||||
.mul,
|
||||
.mulwrap,
|
||||
@ -1640,6 +1645,7 @@ pub const Inst = struct {
|
||||
.is_non_null_ptr = .un_node,
|
||||
.is_non_err = .un_node,
|
||||
.is_non_err_ptr = .un_node,
|
||||
.ret_is_non_err = .un_node,
|
||||
.loop = .pl_node,
|
||||
.repeat = .node,
|
||||
.repeat_inline = .node,
|
||||
|
||||
@ -179,6 +179,7 @@ const Writer = struct {
|
||||
.is_non_null_ptr,
|
||||
.is_non_err,
|
||||
.is_non_err_ptr,
|
||||
.ret_is_non_err,
|
||||
.typeof,
|
||||
.struct_init_empty,
|
||||
.type_info,
|
||||
|
||||
@ -148,3 +148,14 @@ test "simple else prong doesn't emit an error for unreachable else prong" {
|
||||
};
|
||||
try expect(a == 1);
|
||||
}
|
||||
|
||||
test "errdefer used in function that doesn't return an error" {
|
||||
const S = struct {
|
||||
fn foo() u8 {
|
||||
var a: u8 = 5;
|
||||
errdefer a += 1;
|
||||
return a;
|
||||
}
|
||||
};
|
||||
try expect(S.foo() == 5);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user