diff --git a/src/analyze.cpp b/src/analyze.cpp index 41ae69f803..9b776da930 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4771,38 +4771,41 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { if (return_err_set_type->data.error_set.infer_fn != nullptr && return_err_set_type->data.error_set.incomplete) { - ZigType *inferred_err_set_type; + // The inferred error set type is null if the function doesn't + // return any error + ZigType *inferred_err_set_type = nullptr; + if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) { inferred_err_set_type = fn->src_implicit_return_type; } else if (fn->src_implicit_return_type->id == ZigTypeIdErrorUnion) { inferred_err_set_type = fn->src_implicit_return_type->data.error_union.err_set_type; - } else { - add_node_error(g, return_type_node, - buf_sprintf("function with inferred error set must return at least one possible error")); - fn->anal_state = FnAnalStateInvalid; - return; } - if (inferred_err_set_type->data.error_set.infer_fn != nullptr && - inferred_err_set_type->data.error_set.incomplete) - { - if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) { - fn->anal_state = FnAnalStateInvalid; - return; - } - } - - return_err_set_type->data.error_set.incomplete = false; - if (type_is_global_error_set(inferred_err_set_type)) { - return_err_set_type->data.error_set.err_count = UINT32_MAX; - } else { - return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count; - if (inferred_err_set_type->data.error_set.err_count > 0) { - return_err_set_type->data.error_set.errors = heap::c_allocator.allocate(inferred_err_set_type->data.error_set.err_count); - for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) { - return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i]; + if (inferred_err_set_type != nullptr) { + if (inferred_err_set_type->data.error_set.infer_fn != nullptr && + inferred_err_set_type->data.error_set.incomplete) + { + if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) { + fn->anal_state = FnAnalStateInvalid; + return; } } + + return_err_set_type->data.error_set.incomplete = false; + if (type_is_global_error_set(inferred_err_set_type)) { + return_err_set_type->data.error_set.err_count = UINT32_MAX; + } else { + return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count; + if (inferred_err_set_type->data.error_set.err_count > 0) { + return_err_set_type->data.error_set.errors = heap::c_allocator.allocate(inferred_err_set_type->data.error_set.err_count); + for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) { + return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i]; + } + } + } + } else { + return_err_set_type->data.error_set.incomplete = false; + return_err_set_type->data.error_set.err_count = 0; } } } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 0260160dca..5e4f76baf4 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2734,16 +2734,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:5:5: error: else prong required when switching on type 'anyerror'", }); - cases.add("inferred error set with no returned error", - \\export fn entry() void { - \\ foo() catch unreachable; - \\} - \\fn foo() !void { - \\} - , &[_][]const u8{ - "tmp.zig:4:11: error: function with inferred error set must return at least one possible error", - }); - cases.add("error not handled in switch", \\export fn entry() void { \\ foo(452) catch |err| switch (err) { diff --git a/test/stage1/behavior/fn.zig b/test/stage1/behavior/fn.zig index 13859b92ca..c1e5459378 100644 --- a/test/stage1/behavior/fn.zig +++ b/test/stage1/behavior/fn.zig @@ -1,4 +1,7 @@ -const expect = @import("std").testing.expect; +const std = @import("std"); +const testing = std.testing; +const expect = testing.expect; +const expectEqual = testing.expectEqual; test "params" { expect(testParamsAdd(22, 11) == 33); @@ -272,3 +275,12 @@ test "ability to give comptime types and non comptime types to same parameter" { S.doTheTest(); comptime S.doTheTest(); } + +test "function with inferred error set but returning no error" { + const S = struct { + fn foo() !void {} + }; + + const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?; + expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len); +}