From 49ef28a5f1b7ee925f6fc51522bf607d21d1c7bd Mon Sep 17 00:00:00 2001 From: Pavel Verigo Date: Fri, 5 Dec 2025 02:34:51 +0100 Subject: [PATCH] sema: fix error_return_trace_index handling in zirCondBr --- src/Sema.zig | 10 +++++++--- test/behavior/error.zig | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index d31447544c..7651864cdc 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18470,6 +18470,9 @@ fn zirCondbr( break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand); }; + // Reset, this may have been updated by the then block analysis + sub_block.error_return_trace_index = parent_block.error_return_trace_index; + const false_hint: std.builtin.BranchHint = if (err_cond != null and try sema.maybeErrorUnwrap(&sub_block, else_body, err_cond.?, cond_src, false)) h: { @@ -18945,9 +18948,10 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_ while (true) { if (block.label) |label| { if (label.zir_block == zir_block) { - const target_trace_index = if (block.parent) |parent_block| tgt: { - break :tgt parent_block.error_return_trace_index; - } else sema.error_return_trace_index_on_fn_entry; + const target_trace_index = if (block.parent) |parent_block| + parent_block.error_return_trace_index + else + sema.error_return_trace_index_on_fn_entry; if (start_block.error_return_trace_index != target_trace_index) break :b target_trace_index; diff --git a/test/behavior/error.zig b/test/behavior/error.zig index aa39b685ca..d74a7668a9 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -1090,3 +1090,22 @@ test "compare error union to error set" { try S.doTheTest(0); try comptime S.doTheTest(0); } + +test "'if' ignores error via local while 'else' ignores error directly" { + const S = struct { + /// This function is intentionally fallible despite never returning an + /// error so that it participates in error return tracing. + fn testOne(cond: bool) !void { + if (cond) { + const result = notError(); + result catch {}; + } else { + notError() catch {}; + } + } + fn notError() error{E}!void {} + }; + + try S.testOne(false); + try S.testOne(true); +}