mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
* Add compile_bool_op_inner and optimize nested opposite-operator BoolOps to avoid redundant __bool__ calls When a nested BoolOp has the opposite operator (e.g., `And` inside `Or`), the inner BoolOp's short-circuit exits are redirected to skip the outer BoolOp's redundant truth test. This avoids calling `__bool__()` twice on the same value (e.g., `Test() and False or False` previously called `Test().__bool__()` twice instead of once). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add snapshot test for nested BoolOp bytecode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add runtime test for redundant __bool__ check (issue #3567) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Apply clippy and rustfmt * Apply ruff format * Refactor compile_bool_op: extract emit_short_circuit_test and unify with compile_bool_op_inner Reduce code duplication by: - Extracting the repeated Copy + conditional jump pattern into emit_short_circuit_test - Merging compile_bool_op and compile_bool_op_inner into a single compile_bool_op_with_target with an optional short_circuit_target parameter - Keeping compile_bool_op as a thin wrapper for the public interface Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Relocate redundant __bool__ check test snippet * Update extra_tests/snippets/syntax_short_circuit_bool.py * Fix assertion in syntax_short_circuit_bool --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com>
37 lines
1.0 KiB
Python
37 lines
1.0 KiB
Python
# Python carefully avoids evaluating bools more than once in a variety of situations.
|
|
# Eg:
|
|
# In the statement
|
|
# if a or b:
|
|
# it doesn't simply compute (a or b) and then evaluate the result to decide whether to
|
|
# jump. If a is true it jumps directly to the body of the if statement.
|
|
# We can confirm that this behaviour is correct in python code.
|
|
|
|
|
|
# A Bool that raises an exception if evaluated twice!
|
|
class ExplodingBool():
|
|
def __init__(self, value):
|
|
self.value = value
|
|
self.booled = False
|
|
|
|
def __bool__(self):
|
|
assert not self.booled
|
|
self.booled = True
|
|
return self.value
|
|
|
|
y = (ExplodingBool(False) and False and True and False)
|
|
print(y)
|
|
|
|
if (ExplodingBool(True) or False or True or False):
|
|
pass
|
|
|
|
assert ExplodingBool(True) or False
|
|
|
|
while ExplodingBool(False) and False:
|
|
pass
|
|
|
|
# if ExplodingBool(False) and False and True and False:
|
|
# pass
|
|
|
|
# Issue #3567: nested BoolOps should not call __bool__ redundantly
|
|
assert (ExplodingBool(False) and False or False) == False
|