diff --git a/src/analyze.cpp b/src/analyze.cpp index aa5c3c88f..cc90573f4 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5179,11 +5179,14 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { if (fn->anal_state == FnAnalStateInvalid) return ErrorSemanticAnalyzeFail; break; - case FnAnalStateProbing: - add_node_error(g, fn->proto_node, + case FnAnalStateProbing: { + ErrorMsg *msg = add_node_error(g, fn->proto_node, buf_sprintf("cannot resolve '%s': function not fully analyzed yet", buf_ptr(&frame_type->name))); + ir_add_analysis_trace(fn->ir_executable.analysis, msg, + buf_sprintf("depends on its own frame here")); return ErrorSemanticAnalyzeFail; + } } ZigType *fn_type = get_async_fn_type(g, fn->type_entry); @@ -5201,8 +5204,10 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { if (callee->anal_state == FnAnalStateProbing) { ErrorMsg *msg = add_node_error(g, fn->proto_node, buf_sprintf("unable to determine async function frame of '%s'", buf_ptr(&fn->symbol_name))); - add_error_note(g, msg, call->base.source_node, + ErrorMsg *note = add_error_note(g, msg, call->base.source_node, buf_sprintf("analysis of function '%s' depends on the frame", buf_ptr(&callee->symbol_name))); + ir_add_analysis_trace(callee->ir_executable.analysis, note, + buf_sprintf("depends on the frame here")); return ErrorSemanticAnalyzeFail; } diff --git a/src/ir.cpp b/src/ir.cpp index b2389d150..f92434bb3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8217,18 +8217,24 @@ bool ir_gen_fn(CodeGen *codegen, ZigFn *fn_entry) { return ir_gen(codegen, body_node, fn_entry->child_scope, ir_executable); } -static void add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg *err_msg, int limit) { +static void ir_add_call_stack_errors(CodeGen *codegen, IrExecutable *exec, ErrorMsg *err_msg, int limit) { if (!exec || !exec->source_node || limit < 0) return; add_error_note(codegen, err_msg, exec->source_node, buf_sprintf("called from here")); - add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1); + ir_add_call_stack_errors(codegen, exec->parent_exec, err_msg, limit - 1); +} + +void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text) { + IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); + add_error_note(ira->codegen, err_msg, old_instruction->source_node, text); + ir_add_call_stack_errors(ira->codegen, ira->new_irb.exec, err_msg, 10); } static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg) { invalidate_exec(exec); ErrorMsg *err_msg = add_node_error(codegen, source_node, msg); if (exec->parent_exec) { - add_call_stack_errors(codegen, exec, err_msg, 10); + ir_add_call_stack_errors(codegen, exec, err_msg, 10); } return err_msg; } diff --git a/src/ir.hpp b/src/ir.hpp index 597624e2e..3761c5a97 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -28,4 +28,6 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal AstNode *source_node); const char *float_op_to_name(BuiltinFnId op, bool llvm_name); +void ir_add_analysis_trace(IrAnalyze *ira, ErrorMsg *err_msg, Buf *text); + #endif diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 2941cadcf..810e40b18 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,36 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "async function indirectly depends on its own frame", + \\export fn entry() void { + \\ _ = async amain(); + \\} + \\async fn amain() void { + \\ other(); + \\} + \\fn other() void { + \\ var x: [@sizeOf(@Frame(amain))]u8 = undefined; + \\} + , + "tmp.zig:4:1: error: unable to determine async function frame of 'amain'", + "tmp.zig:5:10: note: analysis of function 'other' depends on the frame", + "tmp.zig:8:13: note: depends on the frame here", + ); + + cases.add( + "async function depends on its own frame", + \\export fn entry() void { + \\ _ = async amain(); + \\} + \\async fn amain() void { + \\ var x: [@sizeOf(@Frame(amain))]u8 = undefined; + \\} + , + "tmp.zig:4:1: error: cannot resolve '@Frame(amain)': function not fully analyzed yet", + "tmp.zig:5:13: note: depends on its own frame here", + ); + cases.add( "non async function pointer passed to @asyncCall", \\export fn entry() void {