authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-10-30 12:25:49-07:00
committergravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-10-30 12:38:08-07:00
logca332f57f712c3b4570ca42bc503824022115142
tree4485ea7741ecbfe501eeb2916290d7c911bfffe0
parent2f732deb3d15752d4977f04b38718e6896460e69

stage2: Make `x and false`/`x or true` comptime-known

Same as preceding change, but for stage2.

2 files changed, 66 insertions(+), 7 deletions(-)

src/Sema.zig+16-7
......@@ -15932,12 +15932,10 @@ fn zirBoolBr(
1593215932 const gpa = sema.gpa;
1593315933
1593415934 if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| {
15935 if (lhs_val.toBool() == is_bool_or) {
15936 if (is_bool_or) {
15937 return Air.Inst.Ref.bool_true;
15938 } else {
15939 return Air.Inst.Ref.bool_false;
15940 }
15935 if (is_bool_or and lhs_val.toBool()) {
15936 return Air.Inst.Ref.bool_true;
15937 } else if (!is_bool_or and !lhs_val.toBool()) {
15938 return Air.Inst.Ref.bool_false;
1594115939 }
1594215940 // comptime-known left-hand side. No need for a block here; the result
1594315941 // is simply the rhs expression. Here we rely on there only being 1
......@@ -15977,7 +15975,18 @@ fn zirBoolBr(
1597715975 _ = try rhs_block.addBr(block_inst, rhs_result);
1597815976 }
1597915977
15980 return finishCondBr(sema, parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
15978 const result = finishCondBr(sema, parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
15979 if (!sema.typeOf(rhs_result).isNoReturn()) {
15980 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {
15981 if (is_bool_or and rhs_val.toBool()) {
15982 return Air.Inst.Ref.bool_true;
15983 } else if (!is_bool_or and !rhs_val.toBool()) {
15984 return Air.Inst.Ref.bool_false;
15985 }
15986 }
15987 }
15988
15989 return result;
1598115990}
1598215991
1598315992fn finishCondBr(
test/behavior/eval.zig+50
......@@ -1438,3 +1438,53 @@ test "continue nested inline for loop in named block expr" {
14381438 }
14391439 try expect(a == 2);
14401440}
1441
1442test "x and false is comptime-known false" {
1443 const T = struct {
1444 var x: u32 = 0;
1445
1446 fn foo() bool {
1447 x += 1; // Observable side-effect
1448 return true;
1449 }
1450 };
1451
1452 if (T.foo() and T.foo() and false and T.foo()) {
1453 @compileError("Condition should be comptime-known false");
1454 }
1455 try expect(T.x == 2);
1456
1457 T.x = 0;
1458 if (T.foo() and T.foo() and b: {
1459 _ = T.foo();
1460 break :b false;
1461 } and T.foo()) {
1462 @compileError("Condition should be comptime-known false");
1463 }
1464 try expect(T.x == 3);
1465}
1466
1467test "x or true is comptime-known true" {
1468 const T = struct {
1469 var x: u32 = 0;
1470
1471 fn foo() bool {
1472 x += 1; // Observable side-effect
1473 return false;
1474 }
1475 };
1476
1477 if (!(T.foo() or T.foo() or true or T.foo())) {
1478 @compileError("Condition should be comptime-known false");
1479 }
1480 try expect(T.x == 2);
1481
1482 T.x = 0;
1483 if (!(T.foo() or T.foo() or b: {
1484 _ = T.foo();
1485 break :b true;
1486 } or T.foo())) {
1487 @compileError("Condition should be comptime-known false");
1488 }
1489 try expect(T.x == 3);
1490}