diff --git a/BRANCH_TODO b/BRANCH_TODO index 1efaf1acc..294bb42d5 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,5 +1,4 @@ - * error return tracing - handle `await` and function calls - * go over the commented out tests + * go over the commented out tests in cancel.zig * compile error for error: expected anyframe->T, found 'anyframe' * compile error for error: expected anyframe->T, found 'i32' * await of a non async function diff --git a/src/codegen.cpp b/src/codegen.cpp index 24933bd10..7a27585e4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2300,9 +2300,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable, static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) { if (fn_is_async(g->cur_fn)) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; - bool ret_type_has_bits = instruction->operand != nullptr && - type_has_bits(instruction->operand->value.type); - ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr; + ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; + bool ret_type_has_bits = type_has_bits(ret_type); if (ir_want_runtime_safety(g, &instruction->base)) { LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 59401fbe8..71af5586e 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -39,10 +39,10 @@ comptime { _ = @import("behavior/bugs/828.zig"); _ = @import("behavior/bugs/920.zig"); _ = @import("behavior/byval_arg_var.zig"); - //_ = @import("behavior/cancel.zig"); + _ = @import("behavior/cancel.zig"); _ = @import("behavior/cast.zig"); _ = @import("behavior/const_slice_child.zig"); - //_ = @import("behavior/coroutine_await_struct.zig"); + _ = @import("behavior/coroutine_await_struct.zig"); _ = @import("behavior/coroutines.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); diff --git a/test/stage1/behavior/cancel.zig b/test/stage1/behavior/cancel.zig index efc0df1ae..cb8a07527 100644 --- a/test/stage1/behavior/cancel.zig +++ b/test/stage1/behavior/cancel.zig @@ -1,86 +1,86 @@ const std = @import("std"); -var defer_f1: bool = false; -var defer_f2: bool = false; -var defer_f3: bool = false; - -test "cancel forwards" { - const p = async f1() catch unreachable; - cancel p; - std.testing.expect(defer_f1); - std.testing.expect(defer_f2); - std.testing.expect(defer_f3); -} - -async fn f1() void { - defer { - defer_f1 = true; - } - await (async f2() catch unreachable); -} - -async fn f2() void { - defer { - defer_f2 = true; - } - await (async f3() catch unreachable); -} - -async fn f3() void { - defer { - defer_f3 = true; - } - suspend; -} - -var defer_b1: bool = false; -var defer_b2: bool = false; -var defer_b3: bool = false; -var defer_b4: bool = false; - -test "cancel backwards" { - const p = async b1() catch unreachable; - cancel p; - std.testing.expect(defer_b1); - std.testing.expect(defer_b2); - std.testing.expect(defer_b3); - std.testing.expect(defer_b4); -} - -async fn b1() void { - defer { - defer_b1 = true; - } - await (async b2() catch unreachable); -} - -var b4_handle: promise = undefined; - -async fn b2() void { - const b3_handle = async b3() catch unreachable; - resume b4_handle; - cancel b4_handle; - defer { - defer_b2 = true; - } - const value = await b3_handle; - @panic("unreachable"); -} - -async fn b3() i32 { - defer { - defer_b3 = true; - } - await (async b4() catch unreachable); - return 1234; -} - -async fn b4() void { - defer { - defer_b4 = true; - } - suspend { - b4_handle = @handle(); - } - suspend; -} +//var defer_f1: bool = false; +//var defer_f2: bool = false; +//var defer_f3: bool = false; +// +//test "cancel forwards" { +// const p = async f1() catch unreachable; +// cancel p; +// std.testing.expect(defer_f1); +// std.testing.expect(defer_f2); +// std.testing.expect(defer_f3); +//} +// +//async fn f1() void { +// defer { +// defer_f1 = true; +// } +// await (async f2() catch unreachable); +//} +// +//async fn f2() void { +// defer { +// defer_f2 = true; +// } +// await (async f3() catch unreachable); +//} +// +//async fn f3() void { +// defer { +// defer_f3 = true; +// } +// suspend; +//} +// +//var defer_b1: bool = false; +//var defer_b2: bool = false; +//var defer_b3: bool = false; +//var defer_b4: bool = false; +// +//test "cancel backwards" { +// const p = async b1() catch unreachable; +// cancel p; +// std.testing.expect(defer_b1); +// std.testing.expect(defer_b2); +// std.testing.expect(defer_b3); +// std.testing.expect(defer_b4); +//} +// +//async fn b1() void { +// defer { +// defer_b1 = true; +// } +// await (async b2() catch unreachable); +//} +// +//var b4_handle: promise = undefined; +// +//async fn b2() void { +// const b3_handle = async b3() catch unreachable; +// resume b4_handle; +// cancel b4_handle; +// defer { +// defer_b2 = true; +// } +// const value = await b3_handle; +// @panic("unreachable"); +//} +// +//async fn b3() i32 { +// defer { +// defer_b3 = true; +// } +// await (async b4() catch unreachable); +// return 1234; +//} +// +//async fn b4() void { +// defer { +// defer_b4 = true; +// } +// suspend { +// b4_handle = @handle(); +// } +// suspend; +//} diff --git a/test/stage1/behavior/coroutines.zig b/test/stage1/behavior/coroutines.zig index 7a8edd793..d11f6831b 100644 --- a/test/stage1/behavior/coroutines.zig +++ b/test/stage1/behavior/coroutines.zig @@ -474,3 +474,36 @@ test "suspension points inside branching control flow" { }; S.doTheTest(); } + +test "call async function which has struct return type" { + const S = struct { + var frame: anyframe = undefined; + + fn doTheTest() void { + _ = async atest(); + resume frame; + } + + fn atest() void { + const result = func(); + expect(result.x == 5); + expect(result.y == 6); + } + + const Point = struct { + x: usize, + y: usize, + }; + + fn func() Point { + suspend { + frame = @frame(); + } + return Point{ + .x = 5, + .y = 6, + }; + } + }; + S.doTheTest(); +}