| author | |
| committer | |
| log | 675f01f1768aa08c307640b53e8a5240fa190fab |
| tree | 14702a748268e301cf5fc23a0d28221c487fae7e |
| parent | 1f44b29724b52433d84b43345a52da59f9220e62 |
| parent | e7cc45642138472c29e09cd10e31962426c1aba5 |
| signature |
fix failed assert on generic fn opaque return type4 files changed, 68 insertions(+), 24 deletions(-)
src/analyze.cpp+20-22| ... | ... | @@ -1962,29 +1962,14 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 1962 | 1962 | return g->builtin_types.entry_invalid; |
| 1963 | 1963 | } |
| 1964 | 1964 | |
| 1965 | switch (specified_return_type->id) { | |
| 1966 | case ZigTypeIdInvalid: | |
| 1967 | zig_unreachable(); | |
| 1968 | ||
| 1969 | case ZigTypeIdUndefined: | |
| 1970 | case ZigTypeIdNull: | |
| 1971 | add_node_error(g, fn_proto->return_type, | |
| 1972 | buf_sprintf("return type '%s' not allowed", buf_ptr(&specified_return_type->name))); | |
| 1973 | return g->builtin_types.entry_invalid; | |
| 1974 | ||
| 1975 | case ZigTypeIdOpaque: | |
| 1976 | { | |
| 1977 | ErrorMsg* msg = add_node_error(g, fn_proto->return_type, | |
| 1978 | buf_sprintf("opaque return type '%s' not allowed", buf_ptr(&specified_return_type->name))); | |
| 1979 | Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); | |
| 1980 | if (tld != nullptr) { | |
| 1981 | add_error_note(g, msg, tld->source_node, buf_sprintf("declared here")); | |
| 1982 | } | |
| 1983 | return g->builtin_types.entry_invalid; | |
| 1965 | if(!is_valid_return_type(specified_return_type)){ | |
| 1966 | ErrorMsg* msg = add_node_error(g, fn_proto->return_type, | |
| 1967 | buf_sprintf("%s return type '%s' not allowed", type_id_name(specified_return_type->id), buf_ptr(&specified_return_type->name))); | |
| 1968 | Tld *tld = find_decl(g, &fn_entry->fndef_scope->base, &specified_return_type->name); | |
| 1969 | if (tld != nullptr) { | |
| 1970 | add_error_note(g, msg, tld->source_node, buf_sprintf("type declared here")); | |
| 1984 | 1971 | } |
| 1985 | ||
| 1986 | default: | |
| 1987 | break; | |
| 1972 | return g->builtin_types.entry_invalid; | |
| 1988 | 1973 | } |
| 1989 | 1974 | |
| 1990 | 1975 | if (fn_proto->auto_err_set) { |
| ... | ... | @@ -2056,6 +2041,19 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc |
| 2056 | 2041 | return get_fn_type(g, &fn_type_id); |
| 2057 | 2042 | } |
| 2058 | 2043 | |
| 2044 | bool is_valid_return_type(ZigType* type) { | |
| 2045 | switch (type->id) { | |
| 2046 | case ZigTypeIdInvalid: | |
| 2047 | case ZigTypeIdUndefined: | |
| 2048 | case ZigTypeIdNull: | |
| 2049 | case ZigTypeIdOpaque: | |
| 2050 | return false; | |
| 2051 | default: | |
| 2052 | return true; | |
| 2053 | } | |
| 2054 | zig_unreachable(); | |
| 2055 | } | |
| 2056 | ||
| 2059 | 2057 | bool type_is_invalid(ZigType *type_entry) { |
| 2060 | 2058 | switch (type_entry->id) { |
| 2061 | 2059 | case ZigTypeIdInvalid: |
src/analyze.hpp+1| ... | ... | @@ -267,6 +267,7 @@ ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType * |
| 267 | 267 | void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn); |
| 268 | 268 | bool fn_is_async(ZigFn *fn); |
| 269 | 269 | CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto); |
| 270 | bool is_valid_return_type(ZigType* type); | |
| 270 | 271 | |
| 271 | 272 | Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align); |
| 272 | 273 | Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val, |
src/ir.cpp+13| ... | ... | @@ -19392,6 +19392,19 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19392 | 19392 | ZigType *specified_return_type = ir_analyze_type_expr(ira, impl_fn->child_scope, return_type_node); |
| 19393 | 19393 | if (type_is_invalid(specified_return_type)) |
| 19394 | 19394 | return ira->codegen->invalid_inst_gen; |
| 19395 | ||
| 19396 | if(!is_valid_return_type(specified_return_type)){ | |
| 19397 | ErrorMsg *msg = ir_add_error(ira, source_instr, | |
| 19398 | 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))); | |
| 19399 | add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("function declared here")); | |
| 19400 | ||
| 19401 | Tld *tld = find_decl(ira->codegen, &fn_entry->fndef_scope->base, &specified_return_type->name); | |
| 19402 | if (tld != nullptr) { | |
| 19403 | add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("type declared here")); | |
| 19404 | } | |
| 19405 | return ira->codegen->invalid_inst_gen; | |
| 19406 | } | |
| 19407 | ||
| 19395 | 19408 | if (fn_proto_node->data.fn_proto.auto_err_set) { |
| 19396 | 19409 | ZigType *inferred_err_set_type = get_auto_err_set_type(ira->codegen, impl_fn); |
| 19397 | 19410 | if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusSizeKnown))) |
test/compile_errors.zig+34-2| ... | ... | @@ -6558,9 +6558,41 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 6558 | 6558 | \\export fn bar() !FooType { |
| 6559 | 6559 | \\ return error.InvalidValue; |
| 6560 | 6560 | \\} |
| 6561 | \\export fn bav() !@TypeOf(null) { | |
| 6562 | \\ return error.InvalidValue; | |
| 6563 | \\} | |
| 6564 | \\export fn baz() !@TypeOf(undefined) { | |
| 6565 | \\ return error.InvalidValue; | |
| 6566 | \\} | |
| 6561 | 6567 | , &[_][]const u8{ |
| 6562 | "tmp.zig:2:18: error: opaque return type 'FooType' not allowed", | |
| 6563 | "tmp.zig:1:1: note: declared here", | |
| 6568 | "tmp.zig:2:18: error: Opaque return type 'FooType' not allowed", | |
| 6569 | "tmp.zig:1:1: note: type declared here", | |
| 6570 | "tmp.zig:5:18: error: Null return type '(null)' not allowed", | |
| 6571 | "tmp.zig:8:18: error: Undefined return type '(undefined)' not allowed", | |
| 6572 | }); | |
| 6573 | ||
| 6574 | cases.add("generic function returning opaque type", | |
| 6575 | \\const FooType = @OpaqueType(); | |
| 6576 | \\fn generic(comptime T: type) !T { | |
| 6577 | \\ return undefined; | |
| 6578 | \\} | |
| 6579 | \\export fn bar() void { | |
| 6580 | \\ _ = generic(FooType); | |
| 6581 | \\} | |
| 6582 | \\export fn bav() void { | |
| 6583 | \\ _ = generic(@TypeOf(null)); | |
| 6584 | \\} | |
| 6585 | \\export fn baz() void { | |
| 6586 | \\ _ = generic(@TypeOf(undefined)); | |
| 6587 | \\} | |
| 6588 | , &[_][]const u8{ | |
| 6589 | "tmp.zig:6:16: error: call to generic function with Opaque return type 'FooType' not allowed", | |
| 6590 | "tmp.zig:2:1: note: function declared here", | |
| 6591 | "tmp.zig:1:1: note: type declared here", | |
| 6592 | "tmp.zig:9:16: error: call to generic function with Null return type '(null)' not allowed", | |
| 6593 | "tmp.zig:2:1: note: function declared here", | |
| 6594 | "tmp.zig:12:16: error: call to generic function with Undefined return type '(undefined)' not allowed", | |
| 6595 | "tmp.zig:2:1: note: function declared here", | |
| 6564 | 6596 | }); |
| 6565 | 6597 | |
| 6566 | 6598 | cases.add( // fixed bug #2032 |