From bf4a3df9a961e18a258d94fa35b0c433424e4bbe Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 9 Sep 2022 16:56:59 +0300 Subject: [PATCH] Sema: allow runtime break from inline loop Closes #12787 --- src/Sema.zig | 2 ++ test/behavior/eval.zig | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 53617950ed..71dcfef513 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1353,6 +1353,8 @@ fn analyzeBodyInner( const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime known"); const inline_body = if (cond.val.toBool()) then_body else else_body; + const old_runtime_index = block.runtime_index; + defer block.runtime_index = old_runtime_index; const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse break always_noreturn; if (inst == break_data.block_inst) { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 47d2e4374e..dbbdbf2df3 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -1337,3 +1337,37 @@ test "lazy value is resolved as slice operand" { try expect(@ptrToInt(ptr1) == @ptrToInt(ptr2)); try expect(ptr1.len == ptr2.len); } + +test "break from inline loop depends on runtime condition" { + const S = struct { + fn foo(a: u8) bool { + return a == 4; + } + }; + const arr = [_]u8{ 1, 2, 3, 4 }; + { + const blk = blk: { + inline for (arr) |val| { + if (S.foo(val)) { + break :blk val; + } + } + return error.TestFailed; + }; + try expect(blk == 4); + } + + { + comptime var i = 0; + const blk = blk: { + inline while (i < arr.len) : (i += 1) { + const val = arr[i]; + if (S.foo(val)) { + break :blk val; + } + } + return error.TestFailed; + }; + try expect(blk == 4); + } +}