add compile error for await in exported function

This commit is contained in:
Andrew Kelley 2019-08-14 11:22:12 -04:00
parent 7799423f24
commit f3f838cc01
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 43 additions and 16 deletions

View File

@ -3893,18 +3893,18 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
fn->inferred_async_node = inferred_async_none;
}
static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node) {
ZigType *fn_type = fn_table_entry->type_entry;
static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
ZigType *fn_type = fn->type_entry;
assert(!fn_type->data.fn.is_generic);
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
ZigType *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,
&fn_table_entry->analyzed_executable, fn_type_id->return_type, return_type_node);
fn_table_entry->src_implicit_return_type = block_return_type;
ZigType *block_return_type = ir_analyze(g, &fn->ir_executable,
&fn->analyzed_executable, fn_type_id->return_type, return_type_node);
fn->src_implicit_return_type = block_return_type;
if (type_is_invalid(block_return_type) || fn_table_entry->analyzed_executable.invalid) {
if (type_is_invalid(block_return_type) || fn->analyzed_executable.invalid) {
assert(g->errors.length > 0);
fn_table_entry->anal_state = FnAnalStateInvalid;
fn->anal_state = FnAnalStateInvalid;
return;
}
@ -3912,20 +3912,20 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_typ
ZigType *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type;
if (return_err_set_type->data.error_set.infer_fn != nullptr) {
ZigType *inferred_err_set_type;
if (fn_table_entry->src_implicit_return_type->id == ZigTypeIdErrorSet) {
inferred_err_set_type = fn_table_entry->src_implicit_return_type;
} else if (fn_table_entry->src_implicit_return_type->id == ZigTypeIdErrorUnion) {
inferred_err_set_type = fn_table_entry->src_implicit_return_type->data.error_union.err_set_type;
if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {
inferred_err_set_type = fn->src_implicit_return_type;
} else if (fn->src_implicit_return_type->id == ZigTypeIdErrorUnion) {
inferred_err_set_type = fn->src_implicit_return_type->data.error_union.err_set_type;
} else {
add_node_error(g, return_type_node,
buf_sprintf("function with inferred error set must return at least one possible error"));
fn_table_entry->anal_state = FnAnalStateInvalid;
fn->anal_state = FnAnalStateInvalid;
return;
}
if (inferred_err_set_type->data.error_set.infer_fn != nullptr) {
if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {
fn_table_entry->anal_state = FnAnalStateInvalid;
fn->anal_state = FnAnalStateInvalid;
return;
}
}
@ -3945,12 +3945,25 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_typ
}
}
CallingConvention cc = fn->type_entry->data.fn.fn_type_id.cc;
if (cc != CallingConventionUnspecified && cc != CallingConventionAsync &&
fn->inferred_async_node != nullptr &&
fn->inferred_async_node != inferred_async_checking &&
fn->inferred_async_node != inferred_async_none)
{
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("function with calling convention '%s' cannot be async",
calling_convention_name(cc)));
add_async_error_notes(g, msg, fn);
fn->anal_state = FnAnalStateInvalid;
}
if (g->verbose_ir) {
fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn_table_entry->symbol_name));
ir_print(g, stderr, &fn_table_entry->analyzed_executable, 4);
fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
ir_print(g, stderr, &fn->analyzed_executable, 4);
fprintf(stderr, "}\n");
}
fn_table_entry->anal_state = FnAnalStateComplete;
fn->anal_state = FnAnalStateComplete;
}
static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {

View File

@ -2,6 +2,20 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"invalid suspend in exported function",
\\export fn entry() void {
\\ var frame = async func();
\\ var result = await frame;
\\}
\\fn func() void {
\\ suspend;
\\}
,
"tmp.zig:1:1: error: function with calling convention 'ccc' cannot be async",
"tmp.zig:3:18: note: await is a suspend point",
);
cases.add(
"async function indirectly depends on its own frame",
\\export fn entry() void {