ir: Allow empty inferred error sets

Closes #4564
This commit is contained in:
LemonBoy 2020-02-26 23:17:44 +01:00 committed by Andrew Kelley
parent 0a88352689
commit fd1eade4ca
3 changed files with 40 additions and 35 deletions

View file

@ -4771,18 +4771,17 @@ 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 != nullptr) {
if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&
inferred_err_set_type->data.error_set.incomplete)
{
@ -4804,6 +4803,10 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
}
}
}
} else {
return_err_set_type->data.error_set.incomplete = false;
return_err_set_type->data.error_set.err_count = 0;
}
}
}

View file

@ -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) {

View file

@ -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);
}