Commit 77d098e92d

Andrew Kelley <andrew@ziglang.org>
2019-08-10 23:23:45
fix returning a const error from async function
1 parent 22428a7
Changed files (2)
src
test
stage1
src/codegen.cpp
@@ -2280,13 +2280,16 @@ static LLVMValueRef ir_render_return_begin(CodeGen *g, IrExecutable *executable,
         return operand_has_bits ? ir_llvm_value(g, instruction->operand) : 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);
     LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
-
-    if (ret_type_has_bits && !handle_is_ptr(ret_type)) {
-        // It's a scalar, so it didn't get written to the result ptr. Do that before the atomic rmw.
-        LLVMBuildStore(g->builder, ir_llvm_value(g, instruction->operand), g->cur_ret_ptr);
+    if (operand_has_bits && instruction->operand != nullptr) {
+        ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
+        bool need_store = instruction->operand->value.special != ConstValSpecialRuntime || !handle_is_ptr(ret_type);
+        if (need_store) {
+            // It didn't get written to the result ptr. We do that now so that we do not have to spill
+            // the return operand.
+            ZigType *ret_ptr_type = get_pointer_to_type(g, ret_type, true);
+            gen_assign_raw(g, g->cur_ret_ptr, ret_ptr_type, ir_llvm_value(g, instruction->operand));
+        }
     }
 
     // Prepare to be suspended. We might end up not having to suspend though.
@@ -2387,6 +2390,8 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
         LLVMSetTailCall(call_inst, true);
         LLVMBuildRetVoid(g->builder);
 
+        g->cur_is_after_return = false;
+
         return nullptr;
     }
     if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
@@ -7117,7 +7122,6 @@ static void do_code_gen(CodeGen *g) {
         }
 
         if (is_async) {
-            g->cur_is_after_return = false;
             g->cur_resume_block_count = 0;
 
             LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
test/stage1/behavior/coroutines.zig
@@ -672,3 +672,31 @@ test "try in an async function with error union and non-zero-bit payload" {
     };
     S.doTheTest();
 }
+
+test "returning a const error from async function" {
+    const S = struct {
+        var frame: anyframe = undefined;
+        var ok = false;
+
+        fn doTheTest() void {
+            _ = async amain();
+            resume frame;
+            expect(ok);
+        }
+
+        fn amain() !void {
+            var download_frame = async fetchUrl(10, "a string");
+            const download_text = try await download_frame;
+
+            @panic("should not get here");
+        }
+
+        fn fetchUrl(unused: i32, url: []const u8) ![]u8 {
+            frame = @frame();
+            suspend;
+            ok = true;
+            return error.OutOfMemory;
+        }
+    };
+    S.doTheTest();
+}