From f3227598ebe9ac7e330fea0259d4290ee31e96b9 Mon Sep 17 00:00:00 2001 From: mlugg Date: Thu, 7 Mar 2024 18:43:18 +0000 Subject: [PATCH] Sema: reset block error return trace index between cases Resolves: #19210 --- src/Sema.zig | 11 +++++++++++ test/behavior/switch.zig | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index cff7404a3b..ac73c24911 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12304,6 +12304,7 @@ fn analyzeSwitchRuntimeBlock( extra_index += info.body_len; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; const item = case_vals.items[scalar_i]; // `item` is already guaranteed to be constant known. @@ -12361,6 +12362,7 @@ fn analyzeSwitchRuntimeBlock( case_val_idx += items_len; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; // Generate all possible cases as scalar prongs. if (info.is_inline) { @@ -12392,6 +12394,7 @@ fn analyzeSwitchRuntimeBlock( const item_ref = Air.internedToRef(item.toIntern()); case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) { error.NeededSourceLocation => { @@ -12431,6 +12434,7 @@ fn analyzeSwitchRuntimeBlock( cases_len += 1; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; const analyze_body = if (union_originally) blk: { const item_val = sema.resolveConstDefinedValue(block, .unneeded, item, undefined) catch unreachable; @@ -12576,6 +12580,7 @@ fn analyzeSwitchRuntimeBlock( defer gpa.free(cond_body); case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; const body = sema.code.bodySlice(extra_index, info.body_len); extra_index += info.body_len; @@ -12636,6 +12641,7 @@ fn analyzeSwitchRuntimeBlock( const item_ref = Air.internedToRef(item_val.toIntern()); case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; const analyze_body = if (union_originally) blk: { const field_ty = maybe_union_ty.unionFieldType(item_val, mod).?; @@ -12686,6 +12692,7 @@ fn analyzeSwitchRuntimeBlock( const item_ref = Air.internedToRef(item_val); case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); emit_bb = true; @@ -12716,6 +12723,7 @@ fn analyzeSwitchRuntimeBlock( const item_ref = Air.internedToRef(cur); case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); emit_bb = true; @@ -12743,6 +12751,7 @@ fn analyzeSwitchRuntimeBlock( cases_len += 1; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); emit_bb = true; @@ -12768,6 +12777,7 @@ fn analyzeSwitchRuntimeBlock( cases_len += 1; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src); emit_bb = true; @@ -12796,6 +12806,7 @@ fn analyzeSwitchRuntimeBlock( }; case_block.instructions.shrinkRetainingCapacity(0); + case_block.error_return_trace_index = child_block.error_return_trace_index; if (mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 429caf0e7e..ae33e8e9ab 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -930,3 +930,31 @@ test "prong with inline call to unreachable" { .bool => |ok| try expect(ok), } } + +test "block error return trace index is reset between prongs" { + const S = struct { + fn returnError() error{TestFailed} { + return error.TestFailed; + } + }; + + var x: u1 = 0; + _ = &x; + + const result = switch (x) { + 0 => { + const result: anyerror!i32 = blk: { + break :blk 1; + }; + _ = &result; + }, + 1 => blk: { + const err = switch (x) { + 0 => {}, + 1 => S.returnError(), + }; + break :blk err; + }, + }; + try result; +}