authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-06 19:07:25-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-06 19:07:25-04:00
log1afbb53661e655906980668f0224804118a9862e
treeb75f4327c961c0a7fe62e1601621f936eb55e3c5
parent966c9ea63c635a12c923d3ab155a9070affb18c5
signature Commit is signed but in an unrecognized format.

fix awaiting when result type is a struct


5 files changed, 122 insertions(+), 91 deletions(-)

BRANCH_TODO+1-2
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1 * error return tracing - handle `await` and function calls1 * go over the commented out tests in cancel.zig
2 * go over the commented out tests
3 * compile error for error: expected anyframe->T, found 'anyframe'2 * compile error for error: expected anyframe->T, found 'anyframe'
4 * compile error for error: expected anyframe->T, found 'i32'3 * compile error for error: expected anyframe->T, found 'i32'
5 * await of a non async function4 * await of a non async function
src/codegen.cpp+2-3
...@@ -2300,9 +2300,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,...@@ -2300,9 +2300,8 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
2300static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {2300static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {
2301 if (fn_is_async(g->cur_fn)) {2301 if (fn_is_async(g->cur_fn)) {
2302 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;2302 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2303 bool ret_type_has_bits = instruction->operand != nullptr &&2303 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2304 type_has_bits(instruction->operand->value.type);2304 bool ret_type_has_bits = type_has_bits(ret_type);
2305 ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr;
23062305
2307 if (ir_want_runtime_safety(g, &instruction->base)) {2306 if (ir_want_runtime_safety(g, &instruction->base)) {
2308 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);2307 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
test/stage1/behavior.zig+2-2
...@@ -39,10 +39,10 @@ comptime {...@@ -39,10 +39,10 @@ comptime {
39 _ = @import("behavior/bugs/828.zig");39 _ = @import("behavior/bugs/828.zig");
40 _ = @import("behavior/bugs/920.zig");40 _ = @import("behavior/bugs/920.zig");
41 _ = @import("behavior/byval_arg_var.zig");41 _ = @import("behavior/byval_arg_var.zig");
42 //_ = @import("behavior/cancel.zig");42 _ = @import("behavior/cancel.zig");
43 _ = @import("behavior/cast.zig");43 _ = @import("behavior/cast.zig");
44 _ = @import("behavior/const_slice_child.zig");44 _ = @import("behavior/const_slice_child.zig");
45 //_ = @import("behavior/coroutine_await_struct.zig");45 _ = @import("behavior/coroutine_await_struct.zig");
46 _ = @import("behavior/coroutines.zig");46 _ = @import("behavior/coroutines.zig");
47 _ = @import("behavior/defer.zig");47 _ = @import("behavior/defer.zig");
48 _ = @import("behavior/enum.zig");48 _ = @import("behavior/enum.zig");
test/stage1/behavior/cancel.zig+84-84
...@@ -1,86 +1,86 @@...@@ -1,86 +1,86 @@
1const std = @import("std");1const std = @import("std");
22
3var defer_f1: bool = false;3//var defer_f1: bool = false;
4var defer_f2: bool = false;4//var defer_f2: bool = false;
5var defer_f3: bool = false;5//var defer_f3: bool = false;
66//
7test "cancel forwards" {7//test "cancel forwards" {
8 const p = async<std.heap.direct_allocator> f1() catch unreachable;8// const p = async<std.heap.direct_allocator> f1() catch unreachable;
9 cancel p;9// cancel p;
10 std.testing.expect(defer_f1);10// std.testing.expect(defer_f1);
11 std.testing.expect(defer_f2);11// std.testing.expect(defer_f2);
12 std.testing.expect(defer_f3);12// std.testing.expect(defer_f3);
13}13//}
1414//
15async fn f1() void {15//async fn f1() void {
16 defer {16// defer {
17 defer_f1 = true;17// defer_f1 = true;
18 }18// }
19 await (async f2() catch unreachable);19// await (async f2() catch unreachable);
20}20//}
2121//
22async fn f2() void {22//async fn f2() void {
23 defer {23// defer {
24 defer_f2 = true;24// defer_f2 = true;
25 }25// }
26 await (async f3() catch unreachable);26// await (async f3() catch unreachable);
27}27//}
2828//
29async fn f3() void {29//async fn f3() void {
30 defer {30// defer {
31 defer_f3 = true;31// defer_f3 = true;
32 }32// }
33 suspend;33// suspend;
34}34//}
3535//
36var defer_b1: bool = false;36//var defer_b1: bool = false;
37var defer_b2: bool = false;37//var defer_b2: bool = false;
38var defer_b3: bool = false;38//var defer_b3: bool = false;
39var defer_b4: bool = false;39//var defer_b4: bool = false;
4040//
41test "cancel backwards" {41//test "cancel backwards" {
42 const p = async<std.heap.direct_allocator> b1() catch unreachable;42// const p = async<std.heap.direct_allocator> b1() catch unreachable;
43 cancel p;43// cancel p;
44 std.testing.expect(defer_b1);44// std.testing.expect(defer_b1);
45 std.testing.expect(defer_b2);45// std.testing.expect(defer_b2);
46 std.testing.expect(defer_b3);46// std.testing.expect(defer_b3);
47 std.testing.expect(defer_b4);47// std.testing.expect(defer_b4);
48}48//}
4949//
50async fn b1() void {50//async fn b1() void {
51 defer {51// defer {
52 defer_b1 = true;52// defer_b1 = true;
53 }53// }
54 await (async b2() catch unreachable);54// await (async b2() catch unreachable);
55}55//}
5656//
57var b4_handle: promise = undefined;57//var b4_handle: promise = undefined;
5858//
59async fn b2() void {59//async fn b2() void {
60 const b3_handle = async b3() catch unreachable;60// const b3_handle = async b3() catch unreachable;
61 resume b4_handle;61// resume b4_handle;
62 cancel b4_handle;62// cancel b4_handle;
63 defer {63// defer {
64 defer_b2 = true;64// defer_b2 = true;
65 }65// }
66 const value = await b3_handle;66// const value = await b3_handle;
67 @panic("unreachable");67// @panic("unreachable");
68}68//}
6969//
70async fn b3() i32 {70//async fn b3() i32 {
71 defer {71// defer {
72 defer_b3 = true;72// defer_b3 = true;
73 }73// }
74 await (async b4() catch unreachable);74// await (async b4() catch unreachable);
75 return 1234;75// return 1234;
76}76//}
7777//
78async fn b4() void {78//async fn b4() void {
79 defer {79// defer {
80 defer_b4 = true;80// defer_b4 = true;
81 }81// }
82 suspend {82// suspend {
83 b4_handle = @handle();83// b4_handle = @handle();
84 }84// }
85 suspend;85// suspend;
86}86//}
test/stage1/behavior/coroutines.zig+33
...@@ -474,3 +474,36 @@ test "suspension points inside branching control flow" {...@@ -474,3 +474,36 @@ test "suspension points inside branching control flow" {
474 };474 };
475 S.doTheTest();475 S.doTheTest();
476}476}
477
478test "call async function which has struct return type" {
479 const S = struct {
480 var frame: anyframe = undefined;
481
482 fn doTheTest() void {
483 _ = async atest();
484 resume frame;
485 }
486
487 fn atest() void {
488 const result = func();
489 expect(result.x == 5);
490 expect(result.y == 6);
491 }
492
493 const Point = struct {
494 x: usize,
495 y: usize,
496 };
497
498 fn func() Point {
499 suspend {
500 frame = @frame();
501 }
502 return Point{
503 .x = 5,
504 .y = 6,
505 };
506 }
507 };
508 S.doTheTest();
509}