detect non-async function pointer of inferred async function

closes #3075
master
Andrew Kelley 2019-08-17 16:49:23 -04:00
parent 0ff396c34f
commit 66a490c27c
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
4 changed files with 43 additions and 2 deletions

View File

@ -1396,6 +1396,7 @@ struct ZigFn {
AstNode *set_cold_node;
const AstNode *inferred_async_node;
ZigFn *inferred_async_fn;
AstNode *non_async_node;
ZigList<GlobalExport> export_list;
ZigList<IrInstructionCallGen *> call_list;

View File

@ -4144,8 +4144,15 @@ void semantic_analyze(CodeGen *g) {
// second pass over functions for detecting async
for (g->fn_defs_index = 0; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) {
ZigFn *fn_entry = g->fn_defs.at(g->fn_defs_index);
analyze_fn_async(g, fn_entry, true);
ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
analyze_fn_async(g, fn, true);
if (fn_is_async(fn) && fn->non_async_node != nullptr) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));
add_error_note(g, msg, fn->non_async_node,
buf_sprintf("required to be non-async here"));
add_async_error_notes(g, msg, fn);
}
}
}

View File

@ -15160,6 +15160,20 @@ no_mem_slot:
return var_ptr_instruction;
}
// This function is called when a comptime value becomes accessible at runtime.
static void mark_comptime_value_escape(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *val) {
ir_assert(value_is_comptime(val), source_instr);
if (val->special == ConstValSpecialUndef)
return;
if (val->type->id == ZigTypeIdFn && val->type->data.fn.fn_type_id.cc == CallingConventionUnspecified) {
ir_assert(val->data.x_ptr.special == ConstPtrSpecialFunction, source_instr);
if (val->data.x_ptr.data.fn.fn_entry->non_async_node == nullptr) {
val->data.x_ptr.data.fn.fn_entry->non_async_node = source_instr->source_node;
}
}
}
static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const)
{
@ -15256,6 +15270,10 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
break;
}
if (instr_is_comptime(value)) {
mark_comptime_value_escape(ira, source_instr, &value->value);
}
IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
source_instr->source_node, ptr, value);
return &store_ptr->base;

View File

@ -2,6 +2,21 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"non-async function pointer eventually is inferred to become async",
\\export fn a() void {
\\ var non_async_fn: fn () void = undefined;
\\ non_async_fn = func;
\\}
\\fn func() void {
\\ suspend;
\\}
,
"tmp.zig:5:1: error: 'func' cannot be async",
"tmp.zig:3:20: note: required to be non-async here",
"tmp.zig:6:5: note: suspends here",
);
cases.add(
"bad alignment in @asyncCall",
\\export fn entry() void {