From 7782c76bee0201227be730ae131171939f728538 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Thu, 5 Mar 2020 08:32:09 +0100 Subject: [PATCH 1/2] fix failed assert on generic fn opaque return type --- src/analyze.cpp | 42 ++++++++++++++++++++--------------------- src/analyze.hpp | 1 + src/ir.cpp | 13 +++++++++++++ test/compile_errors.zig | 18 ++++++++++++++++-- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 7712f0f70..638a31ab5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1955,29 +1955,14 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc return g->builtin_types.entry_invalid; } - switch (specified_return_type->id) { - case ZigTypeIdInvalid: - zig_unreachable(); - - case ZigTypeIdUndefined: - case ZigTypeIdNull: - add_node_error(g, fn_proto->return_type, - buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name))); - return g->builtin_types.entry_invalid; - - case ZigTypeIdOpaque: - { - ErrorMsg* msg = add_node_error(g, fn_proto->return_type, - buf_sprintf("opaque return type '%s' not allowed", buf_ptr(&specified_return_type->name))); - Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); - if (tld != nullptr) { - add_error_note(g, msg, tld->source_node, buf_sprintf("declared here")); - } - return g->builtin_types.entry_invalid; + if(!is_valid_return_type(specified_return_type)){ + ErrorMsg* msg = add_node_error(g, fn_proto->return_type, + buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); + if (tld != nullptr) { + add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here")); } - - default: - break; + return g->builtin_types.entry_invalid; } if (fn_proto->auto_err_set) { @@ -2049,6 +2034,19 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc return get_fn_type(g, &fn_type_id); } +bool is_valid_return_type(ZigType* type) { + switch (type->id) { + case ZigTypeIdInvalid: + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdOpaque: + return false; + default: + return true; + } + zig_unreachable(); +} + bool type_is_invalid(ZigType *type_entry) { switch (type_entry->id) { case ZigTypeIdInvalid: diff --git a/src/analyze.hpp b/src/analyze.hpp index fded1e405..84d319bf5 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -265,6 +265,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType * void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn); bool fn_is_async(ZigFn *fn); CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto); +bool is_valid_return_type(ZigType* type); Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align); Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val, diff --git a/src/ir.cpp b/src/ir.cpp index 34f3ef26a..67eabf504 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19339,6 +19339,19 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node); if (type_is_invalid(specified_return_type)) return ira->codegen->invalid_inst_gen; + + if(!is_valid_return_type(specified_return_type)){ + ErrorMsg *msg = ir_add_error(ira, source_instr, + buf_sprintf("call to generic function with return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here")); + + Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name); + if (tld != nullptr) { + add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("type declared here")); + } + return ira->codegen->invalid_inst_gen; + } + if (fn_proto_node->data.fn_proto.auto_err_set) { ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn); if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown))) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index e402197a8..006bd3ef7 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6539,8 +6539,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return error.InvalidValue; \\} , &[_][]const u8{ - "tmp.zig:2:18: error: opaque return type 'FooType' not allowed", - "tmp.zig:1:1: note: declared here", + "tmp.zig:2:18: error: return type 'FooType' not allowed", + "tmp.zig:1:1: note: type declared here", + }); + + cases.add("generic function returning opaque type", + \\const FooType = @OpaqueType(); + \\fn generic(comptime T: type) !T { + \\ return undefined; + \\} + \\export fn bar() void { + \\ _ = generic(FooType); + \\} + , &[_][]const u8{ + "tmp.zig:6:16: error: call to generic function with return type 'FooType' not allowed", + "tmp.zig:2:1: note: function declared here", + "tmp.zig:1:1: note: type declared here", }); cases.add( // fixed bug #2032 From e7cc45642138472c29e09cd10e31962426c1aba5 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Mon, 9 Mar 2020 19:36:15 +0100 Subject: [PATCH 2/2] better error messages and more tests --- src/analyze.cpp | 2 +- src/ir.cpp | 2 +- test/compile_errors.zig | 22 ++++++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 638a31ab5..89e64ec54 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1957,7 +1957,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc if(!is_valid_return_type(specified_return_type)){ ErrorMsg* msg = add_node_error(g, fn_proto->return_type, - buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + buf_sprintf("%s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name))); Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); if (tld != nullptr) { add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here")); diff --git a/src/ir.cpp b/src/ir.cpp index 67eabf504..d4db5455f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19342,7 +19342,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if(!is_valid_return_type(specified_return_type)){ ErrorMsg *msg = ir_add_error(ira, source_instr, - buf_sprintf("call to generic function with return type '%s' not allowed", buf_ptr(&specified_return_type->name))); + buf_sprintf("call to generic function with %s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name))); add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here")); Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 006bd3ef7..63a8a48be 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6538,9 +6538,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn bar() !FooType { \\ return error.InvalidValue; \\} + \\export fn bav() !@TypeOf(null) { + \\ return error.InvalidValue; + \\} + \\export fn baz() !@TypeOf(undefined) { + \\ return error.InvalidValue; + \\} , &[_][]const u8{ - "tmp.zig:2:18: error: return type 'FooType' not allowed", + "tmp.zig:2:18: error: Opaque return type 'FooType' not allowed", "tmp.zig:1:1: note: type declared here", + "tmp.zig:5:18: error: Null return type '(null)' not allowed", + "tmp.zig:8:18: error: Undefined return type '(undefined)' not allowed", }); cases.add("generic function returning opaque type", @@ -6551,10 +6559,20 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn bar() void { \\ _ = generic(FooType); \\} + \\export fn bav() void { + \\ _ = generic(@TypeOf(null)); + \\} + \\export fn baz() void { + \\ _ = generic(@TypeOf(undefined)); + \\} , &[_][]const u8{ - "tmp.zig:6:16: error: call to generic function with return type 'FooType' not allowed", + "tmp.zig:6:16: error: call to generic function with Opaque return type 'FooType' not allowed", "tmp.zig:2:1: note: function declared here", "tmp.zig:1:1: note: type declared here", + "tmp.zig:9:16: error: call to generic function with Null return type '(null)' not allowed", + "tmp.zig:2:1: note: function declared here", + "tmp.zig:12:16: error: call to generic function with Undefined return type '(undefined)' not allowed", + "tmp.zig:2:1: note: function declared here", }); cases.add( // fixed bug #2032