Skip to content

Commit 932f941

Browse files
authored
[ty] fix binary expression inference between boolean literals and bool instances (#18663)
1 parent 87f0feb commit 932f941

File tree

2 files changed

+80
-16
lines changed

2 files changed

+80
-16
lines changed

crates/ty_python_semantic/resources/mdtest/binary/booleans.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,65 @@ def _(a: bool):
103103
reveal_type(x / y) # revealed: int | float
104104
reveal_type(x % y) # revealed: int
105105
```
106+
107+
## Bitwise operations with a variable
108+
109+
```py
110+
import random
111+
112+
def _(a: bool):
113+
def lhs_is_int(x: int):
114+
reveal_type(x | a) # revealed: int
115+
reveal_type(x & a) # revealed: int
116+
reveal_type(x ^ a) # revealed: int
117+
118+
def rhs_is_int(x: int):
119+
reveal_type(a | x) # revealed: int
120+
reveal_type(a & x) # revealed: int
121+
reveal_type(a ^ x) # revealed: int
122+
123+
def lhs_is_int_literal():
124+
reveal_type(0 | a) # revealed: int
125+
reveal_type(0 & a) # revealed: int
126+
reveal_type(0 ^ a) # revealed: int
127+
128+
reveal_type(1 | a) # revealed: int
129+
reveal_type(1 & a) # revealed: int
130+
reveal_type(1 ^ a) # revealed: int
131+
132+
def lhs_is_true():
133+
reveal_type(True | a) # revealed: bool
134+
reveal_type(True & a) # revealed: bool
135+
reveal_type(True ^ a) # revealed: bool
136+
137+
def rhs_is_true():
138+
reveal_type(a | True) # revealed: bool
139+
reveal_type(a & True) # revealed: bool
140+
reveal_type(a ^ True) # revealed: bool
141+
142+
def lhs_is_false():
143+
reveal_type(False | a) # revealed: bool
144+
reveal_type(False & a) # revealed: bool
145+
reveal_type(False ^ a) # revealed: bool
146+
147+
def rhs_is_false():
148+
reveal_type(a | False) # revealed: bool
149+
reveal_type(a & False) # revealed: bool
150+
reveal_type(a ^ False) # revealed: bool
151+
152+
def both_are_bool(x: bool, y: bool):
153+
reveal_type(x | y) # revealed: bool
154+
reveal_type(x & y) # revealed: bool
155+
reveal_type(x ^ y) # revealed: bool
156+
157+
def lhs_is_int_literal_rhs_is_bool_literal():
158+
reveal_type(0 & True) # revealed: Literal[0]
159+
reveal_type(0 | True) # revealed: Literal[1]
160+
reveal_type(3 & True) # revealed: Literal[1]
161+
reveal_type(3 | True) # revealed: Literal[3]
162+
163+
reveal_type(0 & False) # revealed: Literal[0]
164+
reveal_type(0 | False) # revealed: Literal[0]
165+
reveal_type(3 & False) # revealed: Literal[0]
166+
reveal_type(3 | False) # revealed: Literal[3]
167+
```

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6893,22 +6893,22 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
68936893
(Type::BooleanLiteral(b1), Type::BooleanLiteral(b2), ast::Operator::BitXor) => {
68946894
Some(Type::BooleanLiteral(b1 ^ b2))
68956895
}
6896-
6897-
(Type::BooleanLiteral(bool_value), right, op) => self.infer_binary_expression_type(
6898-
node,
6899-
emitted_division_by_zero_diagnostic,
6900-
Type::IntLiteral(i64::from(bool_value)),
6901-
right,
6902-
op,
6903-
),
6904-
(left, Type::BooleanLiteral(bool_value), op) => self.infer_binary_expression_type(
6905-
node,
6906-
emitted_division_by_zero_diagnostic,
6907-
left,
6908-
Type::IntLiteral(i64::from(bool_value)),
6909-
op,
6910-
),
6911-
6896+
(Type::BooleanLiteral(b1), Type::BooleanLiteral(_) | Type::IntLiteral(_), op) => self
6897+
.infer_binary_expression_type(
6898+
node,
6899+
emitted_division_by_zero_diagnostic,
6900+
Type::IntLiteral(i64::from(b1)),
6901+
right_ty,
6902+
op,
6903+
),
6904+
(Type::IntLiteral(_), Type::BooleanLiteral(b2), op) => self
6905+
.infer_binary_expression_type(
6906+
node,
6907+
emitted_division_by_zero_diagnostic,
6908+
left_ty,
6909+
Type::IntLiteral(i64::from(b2)),
6910+
op,
6911+
),
69126912
(Type::Tuple(lhs), Type::Tuple(rhs), ast::Operator::Add) => {
69136913
// Note: this only works on heterogeneous tuples.
69146914
let lhs_elements = lhs.elements(self.db());
@@ -6927,6 +6927,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
69276927
// fall back on looking for dunder methods on one of the operand types.
69286928
(
69296929
Type::FunctionLiteral(_)
6930+
| Type::BooleanLiteral(_)
69306931
| Type::Callable(..)
69316932
| Type::BoundMethod(_)
69326933
| Type::WrapperDescriptor(_)
@@ -6954,6 +6955,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
69546955
| Type::TypeVar(_)
69556956
| Type::TypeIs(_),
69566957
Type::FunctionLiteral(_)
6958+
| Type::BooleanLiteral(_)
69576959
| Type::Callable(..)
69586960
| Type::BoundMethod(_)
69596961
| Type::WrapperDescriptor(_)

0 commit comments

Comments
 (0)