From 5f0bde63582c800352b2d11e20bec650bd266a6f Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 28 Jul 2020 00:07:15 +0300 Subject: [PATCH] add helpful error note for when function cannot return an error This has caused frequent confusion since it looks like you are handling errors correctly with a try but you forgot to change your return type. --- src/ir.cpp | 27 +++++++++++++++++++++------ test/compile_errors.zig | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 4a86f57e3b..15c4e9ec55 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20603,17 +20603,25 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, return ira->codegen->invalid_inst_gen; } + ZigType *expected_return_type = result_loc->value->type->data.pointer.child_type; + IrInstGen *dummy_value = ir_const(ira, source_instr, return_type); dummy_value->value->special = ConstValSpecialRuntime; IrInstGen *dummy_result = ir_implicit_cast2(ira, source_instr, - dummy_value, result_loc->value->type->data.pointer.child_type); - if (type_is_invalid(dummy_result->value->type)) + dummy_value, expected_return_type); + if (type_is_invalid(dummy_result->value->type)) { + if ((return_type->id == ZigTypeIdErrorUnion || return_type->id == ZigTypeIdErrorSet) && + expected_return_type->id != ZigTypeIdErrorUnion && expected_return_type->id != ZigTypeIdErrorSet) + { + add_error_note(ira->codegen, ira->new_irb.exec->first_err_trace_msg, + ira->explicit_return_type_source_node, buf_create_from_str("function cannot return an error")); + } return ira->codegen->invalid_inst_gen; - ZigType *res_child_type = result_loc->value->type->data.pointer.child_type; - if (res_child_type == ira->codegen->builtin_types.entry_anytype) { - res_child_type = return_type; } - if (!handle_is_ptr(ira->codegen, res_child_type)) { + if (expected_return_type == ira->codegen->builtin_types.entry_anytype) { + expected_return_type = return_type; + } + if (!handle_is_ptr(ira->codegen, expected_return_type)) { ir_reset_result(call_result_loc); result_loc = nullptr; } @@ -30907,6 +30915,13 @@ static IrInstGen *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstSrcEndEx IrInstGen *store_ptr = ir_analyze_store_ptr(ira, &instruction->base.base, result_loc, value, instruction->result_loc->allow_write_through_const); if (type_is_invalid(store_ptr->value->type)) { + if (instruction->result_loc->id == ResultLocIdReturn && + (value->value->type->id == ZigTypeIdErrorUnion || value->value->type->id == ZigTypeIdErrorSet) && + ira->explicit_return_type->id != ZigTypeIdErrorUnion && ira->explicit_return_type->id != ZigTypeIdErrorSet) + { + add_error_note(ira->codegen, ira->new_irb.exec->first_err_trace_msg, + ira->explicit_return_type_source_node, buf_create_from_str("function cannot return an error")); + } return ira->codegen->invalid_inst_gen; } } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 30b8a3c7ff..9b836ac45a 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -18,6 +18,28 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:16: error: sentinels are only allowed on slices and unknown-length pointers", }); + cases.addTest("helpful return type error message", + \\export fn foo() u32 { + \\ return error.Ohno; + \\} + \\fn bar() !u32 { + \\ return error.Ohno; + \\} + \\export fn baz() void { + \\ try bar(); + \\} + \\export fn quux() u32 { + \\ return bar(); + \\} + , &[_][]const u8{ + "tmp.zig:2:17: error: expected type 'u32', found 'error{Ohno}'", + "tmp.zig:1:17: note: function cannot return an error", + "tmp.zig:8:5: error: expected type 'void', found '@TypeOf(bar).ReturnType.ErrorSet'", + "tmp.zig:7:17: note: function cannot return an error", + "tmp.zig:11:15: error: expected type 'u32', found '@TypeOf(bar).ReturnType.ErrorSet!u32'", + "tmp.zig:10:18: note: function cannot return an error", + }); + cases.addTest("int/float conversion to comptime_int/float", \\export fn foo() void { \\ var a: f32 = 2;