authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2026-10-08 16:53:48-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-10-09 15:52:33-07:00
log5ad627a53173fd14e36f189767fabdda48e9f294
tree0bdaeadb4de73a8741d75ea4e4354873163eca68
parent7c793c291683a1ac1758d7cf8cb8a7c239dd6989

Sema: account for inlined blocks in comptime break


2 files changed, 43 insertions(+), 9 deletions(-)

src/Sema.zig+30-9
......@@ -17952,19 +17952,40 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label
1795217952/// break from an inline loop. In such case we must convert it to
1795317953/// a runtime break.
1795417954fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void {
17955 const operand = sema.resolveInst(break_operand);
17956
17957 var target_block: ?*Block = child_block;
17958 while (target_block) |candidate| : (target_block = candidate.parent) {
17959 const label = candidate.label orelse continue;
17960 if (label.zir_block != block_inst) continue;
17961 switch (sema.code.instructions.items(.tag)[@backingInt(label.zir_block)]) {
17962 .block_inline, .block_comptime => continue,
17963 else => {},
17964 }
17965 return sema.addRuntimeBreakToBlock(child_block, candidate, label, operand);
17966 }
17967
1795517968 const labeled_block = try sema.ensurePostHoc(child_block, block_inst);
17969 return sema.addRuntimeBreakToBlock(child_block, &labeled_block.block, &labeled_block.label, operand);
17970}
1795617971
17957 const operand = sema.resolveInst(break_operand);
17958 const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand);
17972fn addRuntimeBreakToBlock(
17973 sema: *Sema,
17974 child_block: *Block,
17975 target_block: *Block,
17976 label: *Block.Label,
17977 operand: Air.Inst.Ref,
17978) !void {
17979 const br_ref = try child_block.addBr(label.merges.block_inst, operand);
1795917980
17960 try labeled_block.label.merges.results.append(sema.gpa, operand);
17961 try labeled_block.label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);
17962 try labeled_block.label.merges.src_locs.append(sema.gpa, null);
17981 try label.merges.results.append(sema.gpa, operand);
17982 try label.merges.br_list.append(sema.gpa, br_ref.toIndex().?);
17983 try label.merges.src_locs.append(sema.gpa, null);
1796317984
17964 labeled_block.block.runtime_index.increment();
17965 if (labeled_block.block.runtime_cond == null and labeled_block.block.runtime_loop == null) {
17966 labeled_block.block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;
17967 labeled_block.block.runtime_loop = child_block.runtime_loop;
17985 target_block.runtime_index.increment();
17986 if (target_block.runtime_cond == null and target_block.runtime_loop == null) {
17987 target_block.runtime_cond = child_block.runtime_cond orelse child_block.runtime_loop;
17988 target_block.runtime_loop = child_block.runtime_loop;
1796817989 }
1796917990}
1797017991
test/behavior/if.zig+13
......@@ -71,6 +71,19 @@ test "labeled break inside comptime if inside runtime if" {
7171 try expect(answer == 42);
7272}
7373
74test "labeled break from comptime block inside runtime if" {
75 var c = true;
76 _ = &c;
77 var reached = false;
78 blk: {
79 if (c) {
80 comptime break :blk;
81 }
82 reached = true;
83 }
84 try expect(!reached);
85}
86
7487test "const result loc, runtime if cond, else unreachable" {
7588 const Num = enum { One, Two };
7689