Commit ab4cba14c8

Andrew Kelley <andrew@ziglang.org>
2019-09-02 20:35:41
fix recursive call of await @asyncCall with struct return type
1 parent d291d3c
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -330,6 +330,8 @@ static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
     while (scope != nullptr) {
         if (scope->id == ScopeIdCompTime)
             return true;
+        if (scope->id == ScopeIdTypeOf)
+            return false;
         if (scope->id == ScopeIdFnDef)
             break;
         scope = scope->parent;
@@ -16075,11 +16077,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
         }
 
         IrInstruction *result_loc;
-        if (call_instruction->is_async_call_builtin) {
-            result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);
-            if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
-                return ira->codegen->invalid_instruction;
-        } else if (handle_is_ptr(impl_fn_type_id->return_type)) {
+        if (handle_is_ptr(impl_fn_type_id->return_type)) {
             result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
                     impl_fn_type_id->return_type, nullptr, true, true, false);
             if (result_loc != nullptr) {
@@ -16091,6 +16089,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
                     result_loc = nullptr;
                 }
             }
+        } else if (call_instruction->is_async_call_builtin) {
+            result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);
+            if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
+                return ira->codegen->invalid_instruction;
         } else {
             result_loc = nullptr;
         }
@@ -16231,11 +16233,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
     }
 
     IrInstruction *result_loc;
-    if (call_instruction->is_async_call_builtin) {
-        result_loc = get_async_call_result_loc(ira, call_instruction, return_type);
-        if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
-            return ira->codegen->invalid_instruction;
-    } else if (handle_is_ptr(return_type)) {
+    if (handle_is_ptr(return_type)) {
         result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
                 return_type, nullptr, true, true, false);
         if (result_loc != nullptr) {
@@ -16247,6 +16245,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
                 result_loc = nullptr;
             }
         }
+    } else if (call_instruction->is_async_call_builtin) {
+        result_loc = get_async_call_result_loc(ira, call_instruction, return_type);
+        if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
+            return ira->codegen->invalid_instruction;
     } else {
         result_loc = nullptr;
     }
test/stage1/behavior/async_fn.zig
@@ -1056,3 +1056,39 @@ test "using @typeOf on a generic function call" {
     resume S.global_frame;
     expect(S.global_ok);
 }
+
+test "recursive call of await @asyncCall with struct return type" {
+    const S = struct {
+        var global_frame: anyframe = undefined;
+        var global_ok = false;
+
+        var buf: [100]u8 align(16) = undefined;
+
+        fn amain(x: var) Foo {
+            if (x == 0) {
+                global_ok = true;
+                return Foo{ .x = 1, .y = 2, .z = 3 };
+            }
+            suspend {
+                global_frame = @frame();
+            }
+            const F = @typeOf(async amain(x - 1));
+            const frame = @intToPtr(*F, @ptrToInt(&buf));
+            return await @asyncCall(frame, {}, amain, x - 1);
+        }
+
+        const Foo = struct {
+            x: u64,
+            y: u64,
+            z: u64,
+        };
+    };
+    var res: S.Foo = undefined;
+    var frame: @typeOf(async S.amain(u32(1))) = undefined;
+    _ = @asyncCall(&frame, &res, S.amain, u32(1));
+    resume S.global_frame;
+    expect(S.global_ok);
+    expect(res.x == 1);
+    expect(res.y == 2);
+    expect(res.z == 3);
+}