From d5e3d5d74cefd64287b92d148f78353cdb84e447 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 7 Jun 2022 16:19:21 +0300 Subject: [PATCH] Sema: make `analyzeIsNonErr` even lazier for inferred error sets --- src/Sema.zig | 22 ++++++++++++++++++++++ test/behavior/error.zig | 15 +++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index d36af5abf2..7bc011e226 100644 --- a/src/Sema.zig +++ b/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; diff --git a/test/behavior/error.zig b/test/behavior/error.zig index b735d70d73..0fedd7dff0 100644 --- a/test/behavior/error.zig +++ b/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(); +}