typecheck the panic function
this adds the prototype of panic to @import("builtin") and then uses it to do an implicit cast of the panic function to this prototype, rather than redoing all the implicit cast logic. closes #1894 closes #1895
This commit is contained in:
parent
7293e012d7
commit
a05e224150
@ -1758,6 +1758,7 @@ struct CodeGen {
|
||||
ZigFn *cur_fn;
|
||||
ZigFn *main_fn;
|
||||
ZigFn *panic_fn;
|
||||
TldFn *panic_tld_fn;
|
||||
AstNode *root_export_decl;
|
||||
|
||||
CacheHash cache_hash;
|
||||
|
@ -1351,7 +1351,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
|
||||
size_t backward_branch_count = 0;
|
||||
return ir_eval_const_value(g, scope, node, type_entry,
|
||||
&backward_branch_count, default_backward_branch_quota,
|
||||
nullptr, nullptr, node, type_name, nullptr);
|
||||
nullptr, nullptr, node, type_name, nullptr, nullptr);
|
||||
}
|
||||
|
||||
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
|
||||
@ -3247,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
|
||||
add_node_error(g, proto_node,
|
||||
buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
|
||||
buf_ptr(&fn_type->name)));
|
||||
}
|
||||
void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
|
||||
ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
|
||||
assert(panic_fn_type_val != nullptr);
|
||||
assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
|
||||
ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
|
||||
|
||||
static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
|
||||
AstNode *proto_node = panic_fn->proto_node;
|
||||
assert(proto_node->type == NodeTypeFnProto);
|
||||
ZigType *fn_type = panic_fn->type_entry;
|
||||
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
|
||||
if (fn_type_id->param_count != 2) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, 0, 0, 0);
|
||||
ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
|
||||
if (fn_type_id->param_info[0].type != const_u8_slice) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
AstNode *fake_decl = allocate<AstNode>(1);
|
||||
*fake_decl = *panic_fn->proto_node;
|
||||
fake_decl->type = NodeTypeSymbol;
|
||||
fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
|
||||
|
||||
ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
|
||||
if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
|
||||
ZigType *actual_return_type = fn_type_id->return_type;
|
||||
if (actual_return_type != g->builtin_types.entry_unreachable) {
|
||||
return wrong_panic_prototype(g, proto_node, fn_type);
|
||||
}
|
||||
// call this for the side effects of casting to panic_fn_type
|
||||
analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
|
||||
}
|
||||
|
||||
ZigType *get_test_fn_type(CodeGen *g) {
|
||||
@ -3371,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
|
||||
if (!fn_table_entry->type_entry->data.fn.is_generic) {
|
||||
if (fn_def_node)
|
||||
g->fn_defs.append(fn_table_entry);
|
||||
}
|
||||
|
||||
if (scope_is_root_decls(tld_fn->base.parent_scope) &&
|
||||
(import == g->root_import || import->package == g->panic_package))
|
||||
if (scope_is_root_decls(tld_fn->base.parent_scope) &&
|
||||
(import == g->root_import || import->package == g->panic_package))
|
||||
{
|
||||
if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
|
||||
g->main_fn = fn_table_entry;
|
||||
} else if ((import->package == g->panic_package || g->have_pub_panic) &&
|
||||
buf_eql_str(&fn_table_entry->symbol_name, "panic"))
|
||||
{
|
||||
if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
|
||||
g->main_fn = fn_table_entry;
|
||||
} else if ((import->package == g->panic_package || g->have_pub_panic) &&
|
||||
buf_eql_str(&fn_table_entry->symbol_name, "panic"))
|
||||
{
|
||||
g->panic_fn = fn_table_entry;
|
||||
typecheck_panic_fn(g, fn_table_entry);
|
||||
}
|
||||
g->panic_fn = fn_table_entry;
|
||||
g->panic_tld_fn = tld_fn;
|
||||
}
|
||||
}
|
||||
} else if (source_node->type == NodeTypeTestDecl) {
|
||||
|
@ -239,4 +239,5 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
|
||||
Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
|
||||
ConstExprValue *const_val, ZigType *wanted_type);
|
||||
|
||||
void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
|
||||
#endif
|
||||
|
@ -7144,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||
" instruction_addresses: []usize,\n"
|
||||
"};\n\n");
|
||||
|
||||
buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
|
||||
|
||||
const char *cur_os = nullptr;
|
||||
{
|
||||
buf_appendf(contents, "pub const Os = enum {\n");
|
||||
@ -7913,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {
|
||||
}
|
||||
}
|
||||
|
||||
typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
|
||||
|
||||
report_errors_and_maybe_exit(g);
|
||||
|
||||
}
|
||||
|
15
src/ir.cpp
15
src/ir.cpp
@ -9949,7 +9949,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
|
||||
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec)
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node)
|
||||
{
|
||||
if (expected_type != nullptr && type_is_invalid(expected_type))
|
||||
return &codegen->invalid_instruction->value;
|
||||
@ -9985,7 +9985,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
|
||||
analyzed_executable->backward_branch_count = backward_branch_count;
|
||||
analyzed_executable->backward_branch_quota = backward_branch_quota;
|
||||
analyzed_executable->begin_scope = scope;
|
||||
ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
|
||||
ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
|
||||
if (type_is_invalid(result_type))
|
||||
return &codegen->invalid_instruction->value;
|
||||
|
||||
@ -10863,10 +10863,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ConstCastResultIdFnIsGeneric:
|
||||
add_error_note(ira->codegen, parent_msg, source_node,
|
||||
buf_sprintf("only one of the functions is generic"));
|
||||
break;
|
||||
case ConstCastResultIdFnAlign: // TODO
|
||||
case ConstCastResultIdFnCC: // TODO
|
||||
case ConstCastResultIdFnVarArgs: // TODO
|
||||
case ConstCastResultIdFnIsGeneric: // TODO
|
||||
case ConstCastResultIdFnReturnType: // TODO
|
||||
case ConstCastResultIdFnArgCount: // TODO
|
||||
case ConstCastResultIdFnGenericArgCount: // TODO
|
||||
@ -13856,7 +13859,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
|
||||
AstNode *body_node = fn_entry->body_node;
|
||||
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
|
||||
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);
|
||||
nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);
|
||||
|
||||
if (inferred_err_set_type != nullptr) {
|
||||
inferred_err_set_type->data.error_set.infer_fn = nullptr;
|
||||
@ -14052,7 +14055,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
|
||||
ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
|
||||
fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
|
||||
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
|
||||
nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
|
||||
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
|
||||
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
|
||||
const_instruction->base.value = *align_result;
|
||||
@ -18464,7 +18467,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
|
||||
ZigType *void_type = ira->codegen->builtin_types.entry_void;
|
||||
ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
|
||||
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
|
||||
&cimport_scope->buf, block_node, nullptr, nullptr);
|
||||
&cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
|
||||
if (type_is_invalid(cimport_result->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
|
@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
||||
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec);
|
||||
IrExecutable *parent_exec, AstNode *expected_type_source_node);
|
||||
|
||||
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
|
||||
ZigType *expected_type, AstNode *expected_type_source_node);
|
||||
|
@ -346,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"Panic declared with wrong type signature in tests",
|
||||
"wrong panic signature, runtime function",
|
||||
\\test "" {}
|
||||
\\
|
||||
\\pub fn panic() void {}
|
||||
\\
|
||||
,
|
||||
".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",
|
||||
".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"wrong panic signature, generic function",
|
||||
\\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
|
||||
\\ while (true) {}
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'",
|
||||
".tmp_source.zig:1:5: note: only one of the functions is generic",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
Loading…
x
Reference in New Issue
Block a user