Skip to content

Commit 5aa9628

Browse files
committed
Sema: handle recursive inferred errors better in analyzeIsNonErrComptimeOnly
Closes #15669
1 parent 0958d5d commit 5aa9628

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

src/Sema.zig

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -678,22 +678,6 @@ test "error union payload is properly aligned" {
678678
if (blk.a != 1) unreachable;
679679
}
680680

681-
test "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-
697681
test "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+
877+
test "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+
}

0 commit comments

Comments
 (0)