| author | |
| committer | |
| log | ca332f57f712c3b4570ca42bc503824022115142 |
| tree | 4485ea7741ecbfe501eeb2916290d7c911bfffe0 |
| parent | 2f732deb3d15752d4977f04b38718e6896460e69 |
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( | ... | @@ -15932,12 +15932,10 @@ fn zirBoolBr( |
| 15932 | const gpa = sema.gpa; | 15932 | const gpa = sema.gpa; |
| 15933 | 15933 | ||
| 15934 | if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| { | 15934 | if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| { |
| 15935 | if (lhs_val.toBool() == is_bool_or) { | 15935 | if (is_bool_or and lhs_val.toBool()) { |
| 15936 | if (is_bool_or) { | 15936 | return Air.Inst.Ref.bool_true; |
| 15937 | return Air.Inst.Ref.bool_true; | 15937 | } else if (!is_bool_or and !lhs_val.toBool()) { |
| 15938 | } else { | 15938 | return Air.Inst.Ref.bool_false; |
| 15939 | return Air.Inst.Ref.bool_false; | ||
| 15940 | } | ||
| 15941 | } | 15939 | } |
| 15942 | // comptime-known left-hand side. No need for a block here; the result | 15940 | // comptime-known left-hand side. No need for a block here; the result |
| 15943 | // is simply the rhs expression. Here we rely on there only being 1 | 15941 | // is simply the rhs expression. Here we rely on there only being 1 |
| ... | @@ -15977,7 +15975,18 @@ fn zirBoolBr( | ... | @@ -15977,7 +15975,18 @@ fn zirBoolBr( |
| 15977 | _ = try rhs_block.addBr(block_inst, rhs_result); | 15975 | _ = try rhs_block.addBr(block_inst, rhs_result); |
| 15978 | } | 15976 | } |
| 15979 | 15977 | ||
| 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; | ||
| 15981 | } | 15990 | } |
| 15982 | 15991 | ||
| 15983 | fn finishCondBr( | 15992 | fn finishCondBr( |
test/behavior/eval.zig+50| ... | @@ -1438,3 +1438,53 @@ test "continue nested inline for loop in named block expr" { | ... | @@ -1438,3 +1438,53 @@ test "continue nested inline for loop in named block expr" { |
| 1438 | } | 1438 | } |
| 1439 | try expect(a == 2); | 1439 | try expect(a == 2); |
| 1440 | } | 1440 | } |
| 1441 | |||
| 1442 | test "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 | |||
| 1467 | test "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 | } |