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
signaturelock-open 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 * error return tracing - handle `await` and function calls
2 * go over the commented out tests
1 * go over the commented out tests in cancel.zig
32 * compile error for error: expected anyframe->T, found 'anyframe'
43 * compile error for error: expected anyframe->T, found 'i32'
54 * 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,
23002300static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *instruction) {
23012301 if (fn_is_async(g->cur_fn)) {
23022302 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
2303 bool ret_type_has_bits = instruction->operand != nullptr &&
2304 type_has_bits(instruction->operand->value.type);
2305 ZigType *ret_type = ret_type_has_bits ? instruction->operand->value.type : nullptr;
2303 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2304 bool ret_type_has_bits = type_has_bits(ret_type);
23062305
23072306 if (ir_want_runtime_safety(g, &instruction->base)) {
23082307 LLVMValueRef new_resume_index = LLVMConstAllOnes(usize_type_ref);
test/stage1/behavior.zig+2-2
......@@ -39,10 +39,10 @@ comptime {
3939 _ = @import("behavior/bugs/828.zig");
4040 _ = @import("behavior/bugs/920.zig");
4141 _ = @import("behavior/byval_arg_var.zig");
42 //_ = @import("behavior/cancel.zig");
42 _ = @import("behavior/cancel.zig");
4343 _ = @import("behavior/cast.zig");
4444 _ = @import("behavior/const_slice_child.zig");
45 //_ = @import("behavior/coroutine_await_struct.zig");
45 _ = @import("behavior/coroutine_await_struct.zig");
4646 _ = @import("behavior/coroutines.zig");
4747 _ = @import("behavior/defer.zig");
4848 _ = @import("behavior/enum.zig");
test/stage1/behavior/cancel.zig+84-84
......@@ -1,86 +1,86 @@
11const std = @import("std");
22
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 const p = async<std.heap.direct_allocator> f1() catch unreachable;
9 cancel p;
10 std.testing.expect(defer_f1);
11 std.testing.expect(defer_f2);
12 std.testing.expect(defer_f3);
13}
14
15async fn f1() void {
16 defer {
17 defer_f1 = true;
18 }
19 await (async f2() catch unreachable);
20}
21
22async fn f2() void {
23 defer {
24 defer_f2 = true;
25 }
26 await (async f3() catch unreachable);
27}
28
29async fn f3() void {
30 defer {
31 defer_f3 = true;
32 }
33 suspend;
34}
35
36var defer_b1: bool = false;
37var defer_b2: bool = false;
38var defer_b3: bool = false;
39var defer_b4: bool = false;
40
41test "cancel backwards" {
42 const p = async<std.heap.direct_allocator> b1() catch unreachable;
43 cancel p;
44 std.testing.expect(defer_b1);
45 std.testing.expect(defer_b2);
46 std.testing.expect(defer_b3);
47 std.testing.expect(defer_b4);
48}
49
50async fn b1() void {
51 defer {
52 defer_b1 = true;
53 }
54 await (async b2() catch unreachable);
55}
56
57var b4_handle: promise = undefined;
58
59async fn b2() void {
60 const b3_handle = async b3() catch unreachable;
61 resume b4_handle;
62 cancel b4_handle;
63 defer {
64 defer_b2 = true;
65 }
66 const value = await b3_handle;
67 @panic("unreachable");
68}
69
70async fn b3() i32 {
71 defer {
72 defer_b3 = true;
73 }
74 await (async b4() catch unreachable);
75 return 1234;
76}
77
78async fn b4() void {
79 defer {
80 defer_b4 = true;
81 }
82 suspend {
83 b4_handle = @handle();
84 }
85 suspend;
86}
3//var defer_f1: bool = false;
4//var defer_f2: bool = false;
5//var defer_f3: bool = false;
6//
7//test "cancel forwards" {
8// const p = async<std.heap.direct_allocator> f1() catch unreachable;
9// cancel p;
10// std.testing.expect(defer_f1);
11// std.testing.expect(defer_f2);
12// std.testing.expect(defer_f3);
13//}
14//
15//async fn f1() void {
16// defer {
17// defer_f1 = true;
18// }
19// await (async f2() catch unreachable);
20//}
21//
22//async fn f2() void {
23// defer {
24// defer_f2 = true;
25// }
26// await (async f3() catch unreachable);
27//}
28//
29//async fn f3() void {
30// defer {
31// defer_f3 = true;
32// }
33// suspend;
34//}
35//
36//var defer_b1: bool = false;
37//var defer_b2: bool = false;
38//var defer_b3: bool = false;
39//var defer_b4: bool = false;
40//
41//test "cancel backwards" {
42// const p = async<std.heap.direct_allocator> b1() catch unreachable;
43// cancel p;
44// std.testing.expect(defer_b1);
45// std.testing.expect(defer_b2);
46// std.testing.expect(defer_b3);
47// std.testing.expect(defer_b4);
48//}
49//
50//async fn b1() void {
51// defer {
52// defer_b1 = true;
53// }
54// await (async b2() catch unreachable);
55//}
56//
57//var b4_handle: promise = undefined;
58//
59//async fn b2() void {
60// const b3_handle = async b3() catch unreachable;
61// resume b4_handle;
62// cancel b4_handle;
63// defer {
64// defer_b2 = true;
65// }
66// const value = await b3_handle;
67// @panic("unreachable");
68//}
69//
70//async fn b3() i32 {
71// defer {
72// defer_b3 = true;
73// }
74// await (async b4() catch unreachable);
75// return 1234;
76//}
77//
78//async fn b4() void {
79// defer {
80// defer_b4 = true;
81// }
82// suspend {
83// b4_handle = @handle();
84// }
85// suspend;
86//}
test/stage1/behavior/coroutines.zig+33
......@@ -474,3 +474,36 @@ test "suspension points inside branching control flow" {
474474 };
475475 S.doTheTest();
476476}
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}