authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-09 16:56:59+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-15 00:48:47+03:00
logbf4a3df9a961e18a258d94fa35b0c433424e4bbe
tree809407bceeb4b385204a13322b0430388801855e
parent002260c27481e50c74dbb3d8998cf8c3b1c472d8

Sema: allow runtime break from inline loop

Closes #12787

2 files changed, 36 insertions(+), 0 deletions(-)

src/Sema.zig+2
...@@ -1353,6 +1353,8 @@ fn analyzeBodyInner(...@@ -1353,6 +1353,8 @@ fn analyzeBodyInner(
1353 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];1353 const else_body = sema.code.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
1354 const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime known");1354 const cond = try sema.resolveInstConst(block, cond_src, extra.data.condition, "condition in comptime branch must be comptime known");
1355 const inline_body = if (cond.val.toBool()) then_body else else_body;1355 const inline_body = if (cond.val.toBool()) then_body else else_body;
1356 const old_runtime_index = block.runtime_index;
1357 defer block.runtime_index = old_runtime_index;
1356 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1358 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1357 break always_noreturn;1359 break always_noreturn;
1358 if (inst == break_data.block_inst) {1360 if (inst == break_data.block_inst) {
test/behavior/eval.zig+34
...@@ -1337,3 +1337,37 @@ test "lazy value is resolved as slice operand" {...@@ -1337,3 +1337,37 @@ test "lazy value is resolved as slice operand" {
1337 try expect(@ptrToInt(ptr1) == @ptrToInt(ptr2));1337 try expect(@ptrToInt(ptr1) == @ptrToInt(ptr2));
1338 try expect(ptr1.len == ptr2.len);1338 try expect(ptr1.len == ptr2.len);
1339}1339}
1340
1341test "break from inline loop depends on runtime condition" {
1342 const S = struct {
1343 fn foo(a: u8) bool {
1344 return a == 4;
1345 }
1346 };
1347 const arr = [_]u8{ 1, 2, 3, 4 };
1348 {
1349 const blk = blk: {
1350 inline for (arr) |val| {
1351 if (S.foo(val)) {
1352 break :blk val;
1353 }
1354 }
1355 return error.TestFailed;
1356 };
1357 try expect(blk == 4);
1358 }
1359
1360 {
1361 comptime var i = 0;
1362 const blk = blk: {
1363 inline while (i < arr.len) : (i += 1) {
1364 const val = arr[i];
1365 if (S.foo(val)) {
1366 break :blk val;
1367 }
1368 }
1369 return error.TestFailed;
1370 };
1371 try expect(blk == 4);
1372 }
1373}