fix awaiting when result type is a struct

This commit is contained in:
Andrew Kelley 2019-08-06 19:07:25 -04:00
parent 966c9ea63c
commit 1afbb53661
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 122 additions and 91 deletions

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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<std.heap.direct_allocator> 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<std.heap.direct_allocator> 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<std.heap.direct_allocator> 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<std.heap.direct_allocator> 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;
//}

View File

@ -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();
}