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(...@@ -29153,8 +29153,6 @@ fn analyzeIsNonErrComptimeOnly(
29153 if (ies.errors.count() != 0) break :blk;29153 if (ies.errors.count() != 0) break :blk;
29154 if (maybe_operand_val == null) {29154 if (maybe_operand_val == null) {
29155 // Try to avoid resolving inferred error set if possible.29155 // Try to avoid resolving inferred error set if possible.
29156 if (ies.errors.count() != 0) break :blk;
29157 if (ies.is_anyerror) break :blk;
29158 for (ies.inferred_error_sets.keys()) |other_ies| {29156 for (ies.inferred_error_sets.keys()) |other_ies| {
29159 if (ies == other_ies) continue;29157 if (ies == other_ies) continue;
29160 try sema.resolveInferredErrorSet(block, src, other_ies);29158 try sema.resolveInferredErrorSet(block, src, other_ies);
...@@ -29166,11 +29164,10 @@ fn analyzeIsNonErrComptimeOnly(...@@ -29166,11 +29164,10 @@ fn analyzeIsNonErrComptimeOnly(
2916629164
29167 if (other_ies.errors.count() != 0) break :blk;29165 if (other_ies.errors.count() != 0) break :blk;
29168 }29166 }
29169 if (ies.func == sema.owner_func) {29167 if (!ies.is_resolved and ies.func.state == .in_progress) {
29170 // We're checking the inferred errorset of the current function and none of29168 // Calling resolveInferredErrorSet would immediately fail
29171 // its child inferred error sets contained any errors meaning that any value29169 // so we'll have to rely on runtime checks.
29172 // so far with this type can't contain errors either.29170 return Air.Inst.Ref.none;
29173 return Air.Inst.Ref.bool_true;
29174 }29171 }
29175 try sema.resolveInferredErrorSet(block, src, ies);29172 try sema.resolveInferredErrorSet(block, src, ies);
29176 if (ies.is_anyerror) break :blk;29173 if (ies.is_anyerror) break :blk;
test/behavior/error.zig+25-16
...@@ -678,22 +678,6 @@ test "error union payload is properly aligned" {...@@ -678,22 +678,6 @@ test "error union payload is properly aligned" {
678 if (blk.a != 1) unreachable;678 if (blk.a != 1) unreachable;
679}679}
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
697test "simple else prong allowed even when all errors handled" {681test "simple else prong allowed even when all errors handled" {
698 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO682 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO683 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -889,3 +873,28 @@ test "optional error set return type" {...@@ -889,3 +873,28 @@ test "optional error set return type" {
889 try expect(null == S.foo(true));873 try expect(null == S.foo(true));
890 try expect(E.A == S.foo(false).?);874 try expect(E.A == S.foo(false).?);
891}875}
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}