authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-17 16:49:23-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-17 16:49:23-04:00
log66a490c27c01c958d8d20dbc289c6b2b934a724e
treeedd444dfae7eb106453f9aa0aa9ec3908c97e2f1
parent0ff396c34f93b60a000e1ee50e881a8c25122b79
signaturelock-open Commit is signed but in an unrecognized format.

detect non-async function pointer of inferred async function

closes #3075

4 files changed, 43 insertions(+), 2 deletions(-)

src/all_types.hpp+1
......@@ -1396,6 +1396,7 @@ struct ZigFn {
13961396 AstNode *set_cold_node;
13971397 const AstNode *inferred_async_node;
13981398 ZigFn *inferred_async_fn;
1399 AstNode *non_async_node;
13991400
14001401 ZigList<GlobalExport> export_list;
14011402 ZigList<IrInstructionCallGen *> call_list;
src/analyze.cpp+9-2
......@@ -4144,8 +4144,15 @@ void semantic_analyze(CodeGen *g) {
41444144
41454145 // second pass over functions for detecting async
41464146 for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
4147 ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
4148 analyze_fn_async(g, fn_entry, true);
4147 ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
4148 analyze_fn_async(g, fn, true);
4149 if (fn_is_async(fn) && fn->non_async_node != nullptr) {
4150 ErrorMsg *msg = add_node_error(g, fn->proto_node,
4151 buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));
4152 add_error_note(g, msg, fn->non_async_node,
4153 buf_sprintf("required to be non-async here"));
4154 add_async_error_notes(g, msg, fn);
4155 }
41494156 }
41504157}
41514158
src/ir.cpp+18
......@@ -15160,6 +15160,20 @@ no_mem_slot:
1516015160 return var_ptr_instruction;
1516115161}
1516215162
15163// This function is called when a comptime value becomes accessible at runtime.
15164static void mark_comptime_value_escape(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *val) {
15165 ir_assert(value_is_comptime(val), source_instr);
15166 if (val->special == ConstValSpecialUndef)
15167 return;
15168
15169 if (val->type->id == ZigTypeIdFn && val->type->data.fn.fn_type_id.cc == CallingConventionUnspecified) {
15170 ir_assert(val->data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
15171 if (val->data.x_ptr.data.fn.fn_entry->non_async_node == nullptr) {
15172 val->data.x_ptr.data.fn.fn_entry->non_async_node = source_instr->source_node;
15173 }
15174 }
15175}
15176
1516315177static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
1516415178 IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const)
1516515179{
......@@ -15256,6 +15270,10 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1525615270 break;
1525715271 }
1525815272
15273 if (instr_is_comptime(value)) {
15274 mark_comptime_value_escape(ira, source_instr, &value->value);
15275 }
15276
1525915277 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
1526015278 source_instr->source_node, ptr, value);
1526115279 return &store_ptr->base;
test/compile_errors.zig+15
......@@ -2,6 +2,21 @@ const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
44pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "non-async function pointer eventually is inferred to become async",
7 \\export fn a() void {
8 \\ var non_async_fn: fn () void = undefined;
9 \\ non_async_fn = func;
10 \\}
11 \\fn func() void {
12 \\ suspend;
13 \\}
14 ,
15 "tmp.zig:5:1: error: 'func' cannot be async",
16 "tmp.zig:3:20: note: required to be non-async here",
17 "tmp.zig:6:5: note: suspends here",
18 );
19
520 cases.add(
621 "bad alignment in @asyncCall",
722 \\export fn entry() void {