From bf7b6fbbdb7d28c0d7dba3e17c46ce156712cfc8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 16 Aug 2019 16:30:24 -0400 Subject: [PATCH] add missing compile error for fn call bad implicit cast when the function's return type handle is a pointer but the result location's result value type handle is not a pointer closes #3055 --- src/ir.cpp | 28 +++++++++++++++++++++------- test/compile_errors.zig | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3287a6bd3..0129081e2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9615,6 +9615,10 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT return cur_type; } + if (prev_type == cur_type) { + continue; + } + if (prev_type->id == ZigTypeIdUnreachable) { prev_inst = cur_inst; continue; @@ -14921,7 +14925,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry); IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, frame_type, nullptr, true, true, false); - if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { + if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { return result_loc; } result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false)); @@ -15638,10 +15642,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c if (handle_is_ptr(impl_fn_type_id->return_type)) { result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, impl_fn_type_id->return_type, nullptr, true, true, false); - if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || - instr_is_unreachable(result_loc))) - { - return result_loc; + if (result_loc != nullptr) { + if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { + return result_loc; + } + if (!handle_is_ptr(result_loc->value.type->data.pointer.child_type)) { + ir_reset_result(call_instruction->result_loc); + result_loc = nullptr; + } } } else { result_loc = nullptr; @@ -15791,8 +15799,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c if (handle_is_ptr(return_type)) { result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, return_type, nullptr, true, true, false); - if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { - return result_loc; + if (result_loc != nullptr) { + if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { + return result_loc; + } + if (!handle_is_ptr(result_loc->value.type->data.pointer.child_type)) { + ir_reset_result(call_instruction->result_loc); + result_loc = nullptr; + } } } else { result_loc = nullptr; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7c9d8fae5..5eec78fa7 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,40 @@ const tests = @import("tests.zig"); const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "result location incompatibility mismatching handle_is_ptr (generic call)", + \\export fn entry() void { + \\ var damn = Container{ + \\ .not_optional = getOptional(i32), + \\ }; + \\} + \\pub fn getOptional(comptime T: type) ?T { + \\ return 0; + \\} + \\pub const Container = struct { + \\ not_optional: i32, + \\}; + , + "tmp.zig:3:36: error: expected type 'i32', found '?i32'", + ); + + cases.add( + "result location incompatibility mismatching handle_is_ptr", + \\export fn entry() void { + \\ var damn = Container{ + \\ .not_optional = getOptional(), + \\ }; + \\} + \\pub fn getOptional() ?i32 { + \\ return 0; + \\} + \\pub const Container = struct { + \\ not_optional: i32, + \\}; + , + "tmp.zig:3:36: error: expected type 'i32', found '?i32'", + ); + cases.add( "const frame cast to anyframe", \\export fn a() void {