authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-15 19:19:28-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-15 19:19:28-05:00
loga05e224150a5a4bcad5ab1b399b43db8a0e28104
treedb8352ab2ca029b95050c78364adc4ac0deb1240
parent7293e012d7956b892380517e914108ffadc6941b
signature Commit is signed but in an unrecognized format.

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

7 files changed, 50 insertions(+), 48 deletions(-)

src/all_types.hpp+1
...@@ -1758,6 +1758,7 @@ struct CodeGen {...@@ -1758,6 +1758,7 @@ struct CodeGen {
1758 ZigFn *cur_fn;1758 ZigFn *cur_fn;
1759 ZigFn *main_fn;1759 ZigFn *main_fn;
1760 ZigFn *panic_fn;1760 ZigFn *panic_fn;
1761 TldFn *panic_tld_fn;
1761 AstNode *root_export_decl;1762 AstNode *root_export_decl;
17621763
1763 CacheHash cache_hash;1764 CacheHash cache_hash;
src/analyze.cpp+22-39
...@@ -1351,7 +1351,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no...@@ -1351,7 +1351,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
1351 size_t backward_branch_count = 0;1351 size_t backward_branch_count = 0;
1352 return ir_eval_const_value(g, scope, node, type_entry,1352 return ir_eval_const_value(g, scope, node, type_entry,
1353 &backward_branch_count, default_backward_branch_quota,1353 &backward_branch_count, default_backward_branch_quota,
1354 nullptr, nullptr, node, type_name, nullptr);1354 nullptr, nullptr, node, type_name, nullptr, nullptr);
1355}1355}
13561356
1357ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {1357ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
...@@ -3247,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {...@@ -3247,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
3247 zig_unreachable();3247 zig_unreachable();
3248}3248}
32493249
3250static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {3250void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
3251 add_node_error(g, proto_node,3251 ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
3252 buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",3252 assert(panic_fn_type_val != nullptr);
3253 buf_ptr(&fn_type->name)));3253 assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
3254}3254 ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
3255
3256static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
3257 AstNode *proto_node = panic_fn->proto_node;
3258 assert(proto_node->type == NodeTypeFnProto);
3259 ZigType *fn_type = panic_fn->type_entry;
3260 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
3261 if (fn_type_id->param_count != 2) {
3262 return wrong_panic_prototype(g, proto_node, fn_type);
3263 }
3264 ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
3265 PtrLenUnknown, 0, 0, 0);
3266 ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
3267 if (fn_type_id->param_info[0].type != const_u8_slice) {
3268 return wrong_panic_prototype(g, proto_node, fn_type);
3269 }
32703255
3271 ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));3256 AstNode *fake_decl = allocate<AstNode>(1);
3272 if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {3257 *fake_decl = *panic_fn->proto_node;
3273 return wrong_panic_prototype(g, proto_node, fn_type);3258 fake_decl->type = NodeTypeSymbol;
3274 }3259 fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
32753260
3276 ZigType *actual_return_type = fn_type_id->return_type;3261 // call this for the side effects of casting to panic_fn_type
3277 if (actual_return_type != g->builtin_types.entry_unreachable) {3262 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
3278 return wrong_panic_prototype(g, proto_node, fn_type);
3279 }
3280}3263}
32813264
3282ZigType *get_test_fn_type(CodeGen *g) {3265ZigType *get_test_fn_type(CodeGen *g) {
...@@ -3371,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -3371,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
3371 if (!fn_table_entry->type_entry->data.fn.is_generic) {3354 if (!fn_table_entry->type_entry->data.fn.is_generic) {
3372 if (fn_def_node)3355 if (fn_def_node)
3373 g->fn_defs.append(fn_table_entry);3356 g->fn_defs.append(fn_table_entry);
3357 }
33743358
3375 if (scope_is_root_decls(tld_fn->base.parent_scope) &&3359 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3376 (import == g->root_import || import->package == g->panic_package))3360 (import == g->root_import || import->package == g->panic_package))
3361 {
3362 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
3363 g->main_fn = fn_table_entry;
3364 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3365 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
3377 {3366 {
3378 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {3367 g->panic_fn = fn_table_entry;
3379 g->main_fn = fn_table_entry;3368 g->panic_tld_fn = tld_fn;
3380 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3381 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
3382 {
3383 g->panic_fn = fn_table_entry;
3384 typecheck_panic_fn(g, fn_table_entry);
3385 }
3386 }3369 }
3387 }3370 }
3388 } else if (source_node->type == NodeTypeTestDecl) {3371 } else if (source_node->type == NodeTypeTestDecl) {
src/analyze.hpp+1
...@@ -239,4 +239,5 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);...@@ -239,4 +239,5 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
239Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,239Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
240 ConstExprValue *const_val, ZigType *wanted_type);240 ConstExprValue *const_val, ZigType *wanted_type);
241241
242void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
242#endif243#endif
src/codegen.cpp+4
...@@ -7144,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7144,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7144 " instruction_addresses: []usize,\n"7144 " instruction_addresses: []usize,\n"
7145 "};\n\n");7145 "};\n\n");
71467146
7147 buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
7148
7147 const char *cur_os = nullptr;7149 const char *cur_os = nullptr;
7148 {7150 {
7149 buf_appendf(contents, "pub const Os = enum {\n");7151 buf_appendf(contents, "pub const Os = enum {\n");
...@@ -7913,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {...@@ -7913,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {
7913 }7915 }
7914 }7916 }
79157917
7918 typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
7919
7916 report_errors_and_maybe_exit(g);7920 report_errors_and_maybe_exit(g);
79177921
7918}7922}
src/ir.cpp+9-6
...@@ -9949,7 +9949,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9949,7 +9949,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9949ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,9949ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9950 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,9950 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
9951 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,9951 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
9952 IrExecutable *parent_exec)9952 IrExecutable *parent_exec, AstNode *expected_type_source_node)
9953{9953{
9954 if (expected_type != nullptr && type_is_invalid(expected_type))9954 if (expected_type != nullptr && type_is_invalid(expected_type))
9955 return &codegen->invalid_instruction->value;9955 return &codegen->invalid_instruction->value;
...@@ -9985,7 +9985,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -9985,7 +9985,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
9985 analyzed_executable->backward_branch_count = backward_branch_count;9985 analyzed_executable->backward_branch_count = backward_branch_count;
9986 analyzed_executable->backward_branch_quota = backward_branch_quota;9986 analyzed_executable->backward_branch_quota = backward_branch_quota;
9987 analyzed_executable->begin_scope = scope;9987 analyzed_executable->begin_scope = scope;
9988 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);9988 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
9989 if (type_is_invalid(result_type))9989 if (type_is_invalid(result_type))
9990 return &codegen->invalid_instruction->value;9990 return &codegen->invalid_instruction->value;
99919991
...@@ -10863,10 +10863,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10863,10 +10863,13 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10863 }10863 }
10864 break;10864 break;
10865 }10865 }
10866 case ConstCastResultIdFnIsGeneric:
10867 add_error_note(ira->codegen, parent_msg, source_node,
10868 buf_sprintf("only one of the functions is generic"));
10869 break;
10866 case ConstCastResultIdFnAlign: // TODO10870 case ConstCastResultIdFnAlign: // TODO
10867 case ConstCastResultIdFnCC: // TODO10871 case ConstCastResultIdFnCC: // TODO
10868 case ConstCastResultIdFnVarArgs: // TODO10872 case ConstCastResultIdFnVarArgs: // TODO
10869 case ConstCastResultIdFnIsGeneric: // TODO
10870 case ConstCastResultIdFnReturnType: // TODO10873 case ConstCastResultIdFnReturnType: // TODO
10871 case ConstCastResultIdFnArgCount: // TODO10874 case ConstCastResultIdFnArgCount: // TODO
10872 case ConstCastResultIdFnGenericArgCount: // TODO10875 case ConstCastResultIdFnGenericArgCount: // TODO
...@@ -13856,7 +13859,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13856,7 +13859,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13856 AstNode *body_node = fn_entry->body_node;13859 AstNode *body_node = fn_entry->body_node;
13857 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,13860 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
13858 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,13861 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
13859 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);13862 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);
1386013863
13861 if (inferred_err_set_type != nullptr) {13864 if (inferred_err_set_type != nullptr) {
13862 inferred_err_set_type->data.error_set.infer_fn = nullptr;13865 inferred_err_set_type->data.error_set.infer_fn = nullptr;
...@@ -14052,7 +14055,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -14052,7 +14055,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
14052 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,14055 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
14053 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),14056 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
14054 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,14057 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
14055 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);14058 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
14056 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,14059 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
14057 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);14060 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
14058 const_instruction->base.value = *align_result;14061 const_instruction->base.value = *align_result;
...@@ -18464,7 +18467,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -18464,7 +18467,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
18464 ZigType *void_type = ira->codegen->builtin_types.entry_void;18467 ZigType *void_type = ira->codegen->builtin_types.entry_void;
18465 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,18468 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
18466 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,18469 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
18467 &cimport_scope->buf, block_node, nullptr, nullptr);18470 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
18468 if (type_is_invalid(cimport_result->type))18471 if (type_is_invalid(cimport_result->type))
18469 return ira->codegen->invalid_instruction;18472 return ira->codegen->invalid_instruction;
1847018473
src/ir.hpp+1-1
...@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);...@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec);19 IrExecutable *parent_exec, AstNode *expected_type_source_node);
2020
21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
22 ZigType *expected_type, AstNode *expected_type_source_node);22 ZigType *expected_type, AstNode *expected_type_source_node);
test/compile_errors.zig+12-2
...@@ -346,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -346,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
346 );346 );
347347
348 cases.add(348 cases.add(
349 "Panic declared with wrong type signature in tests",349 "wrong panic signature, runtime function",
350 \\test "" {}350 \\test "" {}
351 \\351 \\
352 \\pub fn panic() void {}352 \\pub fn panic() void {}
353 \\353 \\
354 ,354 ,
355 ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",355 ".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'",
356 );
357
358 cases.add(
359 "wrong panic signature, generic function",
360 \\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
361 \\ while (true) {}
362 \\}
363 ,
364 ".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'",
365 ".tmp_source.zig:1:5: note: only one of the functions is generic",
356 );366 );
357367
358 cases.add(368 cases.add(