authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-05-12 14:59:26+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-05-12 14:59:26+03:00
log5aa9628de3c6637f45b9d8cf8cbd19c422a74f6f
treed85a0ff14b8b7b36458e12dca631f850b9707744
parent0958d5d7db24222bdcc0fb8e8cdc9838953b9857

Sema: handle recursive inferred errors better in analyzeIsNonErrComptimeOnly

Closes #15669

2 files changed, 29 insertions(+), 23 deletions(-)

src/Sema.zig+4-7
......@@ -29153,8 +29153,6 @@ fn analyzeIsNonErrComptimeOnly(
2915329153 if (ies.errors.count() != 0) break :blk;
2915429154 if (maybe_operand_val == null) {
2915529155 // Try to avoid resolving inferred error set if possible.
29156 if (ies.errors.count() != 0) break :blk;
29157 if (ies.is_anyerror) break :blk;
2915829156 for (ies.inferred_error_sets.keys()) |other_ies| {
2915929157 if (ies == other_ies) continue;
2916029158 try sema.resolveInferredErrorSet(block, src, other_ies);
......@@ -29166,11 +29164,10 @@ fn analyzeIsNonErrComptimeOnly(
2916629164
2916729165 if (other_ies.errors.count() != 0) break :blk;
2916829166 }
29169 if (ies.func == sema.owner_func) {
29170 // We're checking the inferred errorset of the current function and none of
29171 // its child inferred error sets contained any errors meaning that any value
29172 // so far with this type can't contain errors either.
29173 return Air.Inst.Ref.bool_true;
29167 if (!ies.is_resolved and ies.func.state == .in_progress) {
29168 // Calling resolveInferredErrorSet would immediately fail
29169 // so we'll have to rely on runtime checks.
29170 return Air.Inst.Ref.none;
2917429171 }
2917529172 try sema.resolveInferredErrorSet(block, src, ies);
2917629173 if (ies.is_anyerror) break :blk;
test/behavior/error.zig+25-16
......@@ -678,22 +678,6 @@ test "error union payload is properly aligned" {
678678 if (blk.a != 1) unreachable;
679679}
680680
681test "ret_ptr doesn't cause own inferred error set to be resolved" {
682 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
683 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
684
685 const S = struct {
686 fn foo() !void {}
687
688 fn doTheTest() !void {
689 errdefer @compileError("bad");
690
691 return try @This().foo();
692 }
693 };
694 try S.doTheTest();
695}
696
697681test "simple else prong allowed even when all errors handled" {
698682 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
699683 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -889,3 +873,28 @@ test "optional error set return type" {
889873 try expect(null == S.foo(true));
890874 try expect(E.A == S.foo(false).?);
891875}
876
877test "try used in recursive function with inferred error set" {
878 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
879 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
880
881 const Value = union(enum) {
882 values: []const @This(),
883 b,
884
885 fn x(value: @This()) !void {
886 switch (value.values[0]) {
887 .values => return try x(value.values[0]),
888 .b => return error.a,
889 }
890 }
891 };
892 const a = Value{
893 .values = &[1]Value{
894 .{
895 .values = &[1]Value{.{ .b = {} }},
896 },
897 },
898 };
899 try expectError(error.a, Value.x(a));
900}