authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2025-12-05 02:34:51+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-12-07 07:20:59+01:00
logcc099afca557ae427261ab0c5c733738d9d87782
tree66872dd203ddadb5c22553795b51e5535ade72a0
parenta21d9408a3ab20d90b4f410695eb598387afd8d3

sema: fix error_return_trace_index handling in zirCondBr


2 files changed, 26 insertions(+), 3 deletions(-)

src/Sema.zig+7-3
......@@ -18486,6 +18486,9 @@ fn zirCondbr(
1848618486 break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand);
1848718487 };
1848818488
18489 // Reset, this may have been updated by the then block analysis
18490 sub_block.error_return_trace_index = parent_block.error_return_trace_index;
18491
1848918492 const false_hint: std.builtin.BranchHint = if (err_cond != null and
1849018493 try sema.maybeErrorUnwrap(&sub_block, else_body, err_cond.?, cond_src, false))
1849118494 h: {
......@@ -18961,9 +18964,10 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_
1896118964 while (true) {
1896218965 if (block.label) |label| {
1896318966 if (label.zir_block == zir_block) {
18964 const target_trace_index = if (block.parent) |parent_block| tgt: {
18965 break :tgt parent_block.error_return_trace_index;
18966 } else sema.error_return_trace_index_on_fn_entry;
18967 const target_trace_index = if (block.parent) |parent_block|
18968 parent_block.error_return_trace_index
18969 else
18970 sema.error_return_trace_index_on_fn_entry;
1896718971
1896818972 if (start_block.error_return_trace_index != target_trace_index)
1896918973 break :b target_trace_index;
test/behavior/error.zig+19
......@@ -1090,3 +1090,22 @@ test "compare error union to error set" {
10901090 try S.doTheTest(0);
10911091 try comptime S.doTheTest(0);
10921092}
1093
1094test "'if' ignores error via local while 'else' ignores error directly" {
1095 const S = struct {
1096 /// This function is intentionally fallible despite never returning an
1097 /// error so that it participates in error return tracing.
1098 fn testOne(cond: bool) !void {
1099 if (cond) {
1100 const result = notError();
1101 result catch {};
1102 } else {
1103 notError() catch {};
1104 }
1105 }
1106 fn notError() error{E}!void {}
1107 };
1108
1109 try S.testOne(false);
1110 try S.testOne(true);
1111}