authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-02-26 23:17:44+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-26 21:02:22-05:00
logfd1eade4ca02b125b1a2ecea564f32af6a683248
treee77e709dcc872897797de3844e18611ff992f55f
parent0a8835268915feab561bdb68adb17aed76b9708f

ir: Allow empty inferred error sets

Closes #4564

3 files changed, 38 insertions(+), 33 deletions(-)

src/analyze.cpp+25-22
...@@ -4771,38 +4771,41 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {...@@ -4771,38 +4771,41 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
4771 if (return_err_set_type->data.error_set.infer_fn != nullptr &&4771 if (return_err_set_type->data.error_set.infer_fn != nullptr &&
4772 return_err_set_type->data.error_set.incomplete)4772 return_err_set_type->data.error_set.incomplete)
4773 {4773 {
4774 ZigType *inferred_err_set_type;4774 // The inferred error set type is null if the function doesn't
4775 // return any error
4776 ZigType *inferred_err_set_type = nullptr;
4777
4775 if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {4778 if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) {
4776 inferred_err_set_type = fn->src_implicit_return_type;4779 inferred_err_set_type = fn->src_implicit_return_type;
4777 } else if (fn->src_implicit_return_type->id == ZigTypeIdErrorUnion) {4780 } else if (fn->src_implicit_return_type->id == ZigTypeIdErrorUnion) {
4778 inferred_err_set_type = fn->src_implicit_return_type->data.error_union.err_set_type;4781 inferred_err_set_type = fn->src_implicit_return_type->data.error_union.err_set_type;
4779 } else {
4780 add_node_error(g, return_type_node,
4781 buf_sprintf("function with inferred error set must return at least one possible error"));
4782 fn->anal_state = FnAnalStateInvalid;
4783 return;
4784 }4782 }
47854783
4786 if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&4784 if (inferred_err_set_type != nullptr) {
4787 inferred_err_set_type->data.error_set.incomplete)4785 if (inferred_err_set_type->data.error_set.infer_fn != nullptr &&
4788 {4786 inferred_err_set_type->data.error_set.incomplete)
4789 if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {4787 {
4790 fn->anal_state = FnAnalStateInvalid;4788 if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) {
4791 return;4789 fn->anal_state = FnAnalStateInvalid;
4790 return;
4791 }
4792 }4792 }
4793 }
47944793
4795 return_err_set_type->data.error_set.incomplete = false;4794 return_err_set_type->data.error_set.incomplete = false;
4796 if (type_is_global_error_set(inferred_err_set_type)) {4795 if (type_is_global_error_set(inferred_err_set_type)) {
4797 return_err_set_type->data.error_set.err_count = UINT32_MAX;4796 return_err_set_type->data.error_set.err_count = UINT32_MAX;
4798 } else {4797 } else {
4799 return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count;4798 return_err_set_type->data.error_set.err_count = inferred_err_set_type->data.error_set.err_count;
4800 if (inferred_err_set_type->data.error_set.err_count > 0) {4799 if (inferred_err_set_type->data.error_set.err_count > 0) {
4801 return_err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(inferred_err_set_type->data.error_set.err_count);4800 return_err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(inferred_err_set_type->data.error_set.err_count);
4802 for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) {4801 for (uint32_t i = 0; i < inferred_err_set_type->data.error_set.err_count; i += 1) {
4803 return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i];4802 return_err_set_type->data.error_set.errors[i] = inferred_err_set_type->data.error_set.errors[i];
4803 }
4804 }4804 }
4805 }4805 }
4806 } else {
4807 return_err_set_type->data.error_set.incomplete = false;
4808 return_err_set_type->data.error_set.err_count = 0;
4806 }4809 }
4807 }4810 }
4808 }4811 }
test/compile_errors.zig-10
...@@ -2734,16 +2734,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2734,16 +2734,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2734 "tmp.zig:5:5: error: else prong required when switching on type 'anyerror'",2734 "tmp.zig:5:5: error: else prong required when switching on type 'anyerror'",
2735 });2735 });
27362736
2737 cases.add("inferred error set with no returned error",
2738 \\export fn entry() void {
2739 \\ foo() catch unreachable;
2740 \\}
2741 \\fn foo() !void {
2742 \\}
2743 , &[_][]const u8{
2744 "tmp.zig:4:11: error: function with inferred error set must return at least one possible error",
2745 });
2746
2747 cases.add("error not handled in switch",2737 cases.add("error not handled in switch",
2748 \\export fn entry() void {2738 \\export fn entry() void {
2749 \\ foo(452) catch |err| switch (err) {2739 \\ foo(452) catch |err| switch (err) {
test/stage1/behavior/fn.zig+13-1
...@@ -1,4 +1,7 @@...@@ -1,4 +1,7 @@
1const expect = @import("std").testing.expect;1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
25
3test "params" {6test "params" {
4 expect(testParamsAdd(22, 11) == 33);7 expect(testParamsAdd(22, 11) == 33);
...@@ -272,3 +275,12 @@ test "ability to give comptime types and non comptime types to same parameter" {...@@ -272,3 +275,12 @@ test "ability to give comptime types and non comptime types to same parameter" {
272 S.doTheTest();275 S.doTheTest();
273 comptime S.doTheTest();276 comptime S.doTheTest();
274}277}
278
279test "function with inferred error set but returning no error" {
280 const S = struct {
281 fn foo() !void {}
282 };
283
284 const return_ty = @typeInfo(@TypeOf(S.foo)).Fn.return_type.?;
285 expectEqual(0, @typeInfo(@typeInfo(return_ty).ErrorUnion.error_set).ErrorSet.?.len);
286}