Commit d5e3d5d74c

Veikka Tuominen <git@vexu.eu>
2022-06-07 15:19:21
Sema: make `analyzeIsNonErr` even lazier for inferred error sets
1 parent e9fc58e
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -21870,6 +21870,28 @@ fn analyzeIsNonErrComptimeOnly(
             if (ies.is_anyerror) break :blk;
             if (ies.errors.count() != 0) break :blk;
             if (maybe_operand_val == null) {
+                // Try to avoid resolving inferred error set if possible.
+                if (ies.errors.count() != 0) break :blk;
+                if (ies.is_anyerror) break :blk;
+                var it = ies.inferred_error_sets.keyIterator();
+                while (it.next()) |other_error_set_ptr| {
+                    const other_ies: *Module.Fn.InferredErrorSet = other_error_set_ptr.*;
+                    if (ies == other_ies) continue;
+                    try sema.resolveInferredErrorSet(block, src, other_ies);
+                    if (other_ies.is_anyerror) {
+                        ies.is_anyerror = true;
+                        ies.is_resolved = true;
+                        break :blk;
+                    }
+
+                    if (other_ies.errors.count() != 0) break :blk;
+                }
+                if (ies.func == sema.owner_func) {
+                    // We're checking the inferred errorset of the current function and none of
+                    // its child inferred error sets contained any errors meaning that any value
+                    // so far with this type can't contain errors either.
+                    return Air.Inst.Ref.bool_true;
+                }
                 try sema.resolveInferredErrorSet(block, src, ies);
                 if (ies.is_anyerror) break :blk;
                 if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
test/behavior/error.zig
@@ -754,3 +754,18 @@ test "error union payload is properly aligned" {
     const blk = S.foo() catch unreachable;
     if (blk.a != 1) unreachable;
 }
+
+test "ret_ptr doesn't cause own inferred error set to be resolved" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+    const S = struct {
+        fn foo() !void {}
+
+        fn doTheTest() !void {
+            errdefer @compileError("bad");
+
+            return try @This().foo();
+        }
+    };
+    try S.doTheTest();
+}