From 24d78177eec4d8fc3aa8ca99dd50788e38f9f8b6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 3 Aug 2019 01:06:14 -0400 Subject: [PATCH] add compile error for async call of function pointer --- BRANCH_TODO | 2 +- src/ir.cpp | 5 ++++- test/compile_errors.zig | 12 ++++++++++++ test/stage1/behavior/coroutines.zig | 8 ++++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/BRANCH_TODO b/BRANCH_TODO index 92390f099..f3d881f5e 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,4 +1,3 @@ - * struct types as the return type of an async function. make sure it works with return result locations. * compile error for error: expected anyframe->T, found 'anyframe' * compile error for error: expected anyframe->T, found 'i32' * await of a non async function @@ -19,3 +18,4 @@ * make resuming inside a suspend block, with nothing after it, a must-tail call. * make sure there are safety tests for all the new safety features (search the new PanicFnId enum values) * error return tracing + * compile error for casting a function to a non-async function pointer, but then later it gets inferred to be an async function diff --git a/src/ir.cpp b/src/ir.cpp index f140cfeab..b01f43b3e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14819,7 +14819,10 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count) { - ir_assert(fn_entry != nullptr, &call_instruction->base); + if (fn_entry == nullptr) { + ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required")); + return ira->codegen->invalid_instruction; + } ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 272d99c93..4b1a24c67 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,18 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "runtime-known function called with async keyword", + \\export fn entry() void { + \\ var ptr = afunc; + \\ _ = async ptr(); + \\} + \\ + \\async fn afunc() void { } + , + "tmp.zig:3:15: error: function is not comptime-known; @asyncCall required", + ); + cases.add( "function with ccc indirectly calling async function", \\export fn entry() void { diff --git a/test/stage1/behavior/coroutines.zig b/test/stage1/behavior/coroutines.zig index a1c1b7ad6..aa77541d1 100644 --- a/test/stage1/behavior/coroutines.zig +++ b/test/stage1/behavior/coroutines.zig @@ -263,15 +263,15 @@ test "async function with dot syntax" { //test "async fn pointer in a struct field" { // var data: i32 = 1; // const Foo = struct { -// bar: async<*std.mem.Allocator> fn (*i32) void, +// bar: async fn (*i32) void, // }; // var foo = Foo{ .bar = simpleAsyncFn2 }; -// const p = (async foo.bar(&data)) catch unreachable; +// const p = async foo.bar(&data); // expect(data == 2); -// cancel p; +// resume p; // expect(data == 4); //} -//async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { +//async fn simpleAsyncFn2(y: *i32) void { // defer y.* += 2; // y.* += 1; // suspend;