diff --git a/src/codegen.cpp b/src/codegen.cpp index b590995c9..0533cc85b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4122,8 +4122,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr if (!type_has_bits(src_return_type)) return nullptr; - if (result_loc != nullptr) - return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + if (result_loc != nullptr) { + if (instruction->result_loc->id == IrInstructionIdReturnPtr) { + instruction->base.spill = nullptr; + return g->cur_ret_ptr; + } else { + return get_handle_value(g, result_loc, src_return_type, ptr_result_type); + } + } LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); return LLVMBuildLoad(g->builder, result_ptr, ""); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index b8a7196ed..3ee728f8a 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1178,3 +1178,26 @@ test "suspend in for loop" { S.doTheTest(); } +test "correctly spill when returning the error union result of another async fn" { + const S = struct { + var global_frame: anyframe = undefined; + + fn doTheTest() void { + expect((atest() catch unreachable) == 1234); + } + + fn atest() !i32 { + return fallible1(); + } + + fn fallible1() anyerror!i32 { + suspend { + global_frame = @frame(); + } + return 1234; + } + }; + _ = async S.doTheTest(); + resume S.global_frame; +} +