diff --git a/src/analyze.cpp b/src/analyze.cpp index 2dfb540801..e06faba7a9 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1757,6 +1757,32 @@ 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: + case ZigTypeIdArgTuple: + 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; + } + + default: + break; + } + if (fn_proto->auto_err_set) { ZigType *inferred_err_set_type = get_auto_err_set_type(g, fn_entry); if ((err = type_resolve(g, specified_return_type, ResolveStatusSizeKnown))) @@ -1782,15 +1808,11 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc switch (fn_type_id.return_type->id) { case ZigTypeIdInvalid: - zig_unreachable(); - case ZigTypeIdUndefined: case ZigTypeIdNull: case ZigTypeIdArgTuple: case ZigTypeIdOpaque: - add_node_error(g, fn_proto->return_type, - buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name))); - return g->builtin_types.entry_invalid; + zig_unreachable(); case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index d9ad5b7f82..6365ca64cb 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6556,4 +6556,15 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned", ); + + cases.add( + "function returning opaque type", + \\const FooType = @OpaqueType(); + \\export fn bar() !FooType { + \\ return error.InvalidValue; + \\} + , + "tmp.zig:2:18: error: opaque return type 'FooType' not allowed", + "tmp.zig:1:1: note: declared here", + ); }