errdefer and try/defer fix

This commit is contained in:
2026-07-13 19:20:22 +02:00
parent 9e75549d02
commit 6de4d9f9f3
23 changed files with 113190 additions and 105482 deletions
+31 -8
View File
@@ -416,10 +416,11 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
})
if expr.kind == .Try {
result := channel
if !types.equal(channel_type, state.func_result) {
error_value := ir.INVALID_INSTRUCTION
if !types.equal(channel_type, state.func_result) || len(expr.args) > 0 {
error_type := types.fallible_error(channel_type, &state.hir_module.types)
enclosing_error := types.fallible_error(state.func_result, &state.hir_module.types)
error_value := append_instruction(state, ir.Instruction{
error_value = append_instruction(state, ir.Instruction{
op=.Fallible_Error, span=expr.span, type=error_type,
target=ir.INVALID_REF, a=channel_slot, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
@@ -431,14 +432,36 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
diagnostic=source.INVALID_DIAGNOSTIC,
})
}
args := make([]ir.Instruction_Id, 1, state.allocator)
args[0] = error_value
result = append_instruction(state, ir.Instruction{
op=.Aggregate, span=expr.span, type=state.func_result, integer=1,
args=args, target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION,
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
if !types.equal(channel_type, state.func_result) {
args := make([]ir.Instruction_Id, 1, state.allocator)
args[0] = error_value
result = append_instruction(state, ir.Instruction{
op=.Aggregate, span=expr.span, type=state.func_result, integer=1,
args=args, target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION,
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
})
}
}
for encoded_capture in expr.args {
capture := hir.Local_Id(encoded_capture)
if capture == hir.INVALID_LOCAL || int(capture) >= len(state.func_locals) {
continue
}
error_type := state.func_locals[capture].type
capture_slot := append_instruction(state, ir.Instruction{
op=.Alloca, span=expr.span, type=error_type,
target=ir.local_ref(ir.Local_Id(capture)),
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
state.local_slots[capture] = capture_slot
append_instruction(state, ir.Instruction{
op=.Store, span=expr.span, type=error_type,
target=ir.INVALID_REF, a=capture_slot, b=error_value,
diagnostic=source.INVALID_DIAGNOSTIC,
})
}
lower_statements(state, expr.body)
append_instruction(state, ir.Instruction{
op=.Return, span=expr.span, type=state.func_result,
target=ir.INVALID_REF, a=result, b=ir.INVALID_INSTRUCTION,