Skip to content

Commit 5e9259c

Browse files
authored
Don't special-case class instances in binary expression inference (#15161)
Just like in #15045 for unary expressions: In binary expressions, we were only looking for dunder expressions for `Type::Instance` types. We had some special cases for coercing the various `Literal` types into their corresponding `Instance` types before doing the lookup. But we can side-step all of that by using the existing `Type::to_meta_type` and `Type::to_instance` methods.
1 parent d45c1ee commit 5e9259c

File tree

8 files changed

+555
-60
lines changed

8 files changed

+555
-60
lines changed

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,50 @@ reveal_type(a | b) # revealed: Literal[True]
4646
reveal_type(b | a) # revealed: Literal[True]
4747
reveal_type(b | b) # revealed: Literal[False]
4848
```
49+
50+
## Arithmetic with a variable
51+
52+
```py
53+
a = True
54+
b = False
55+
56+
def lhs_is_int(x: int):
57+
reveal_type(x + a) # revealed: int
58+
reveal_type(x - a) # revealed: int
59+
reveal_type(x * a) # revealed: int
60+
reveal_type(x // a) # revealed: int
61+
reveal_type(x / a) # revealed: float
62+
reveal_type(x % a) # revealed: int
63+
64+
def rhs_is_int(x: int):
65+
reveal_type(a + x) # revealed: int
66+
reveal_type(a - x) # revealed: int
67+
reveal_type(a * x) # revealed: int
68+
reveal_type(a // x) # revealed: int
69+
reveal_type(a / x) # revealed: float
70+
reveal_type(a % x) # revealed: int
71+
72+
def lhs_is_bool(x: bool):
73+
reveal_type(x + a) # revealed: int
74+
reveal_type(x - a) # revealed: int
75+
reveal_type(x * a) # revealed: int
76+
reveal_type(x // a) # revealed: int
77+
reveal_type(x / a) # revealed: float
78+
reveal_type(x % a) # revealed: int
79+
80+
def rhs_is_bool(x: bool):
81+
reveal_type(a + x) # revealed: int
82+
reveal_type(a - x) # revealed: int
83+
reveal_type(a * x) # revealed: int
84+
reveal_type(a // x) # revealed: int
85+
reveal_type(a / x) # revealed: float
86+
reveal_type(a % x) # revealed: int
87+
88+
def both_are_bool(x: bool, y: bool):
89+
reveal_type(x + y) # revealed: int
90+
reveal_type(x - y) # revealed: int
91+
reveal_type(x * y) # revealed: int
92+
reveal_type(x // y) # revealed: int
93+
reveal_type(x / y) # revealed: float
94+
reveal_type(x % y) # revealed: int
95+
```
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Binary operations on classes
2+
3+
## Union of two classes
4+
5+
Unioning two classes via the `|` operator is only available in Python 3.10 and later.
6+
7+
```toml
8+
[environment]
9+
python-version = "3.10"
10+
```
11+
12+
```py
13+
class A: ...
14+
class B: ...
15+
16+
reveal_type(A | B) # revealed: UnionType
17+
```
18+
19+
## Union of two classes (prior to 3.10)
20+
21+
```py
22+
class A: ...
23+
class B: ...
24+
25+
# error: "Operator `|` is unsupported between objects of type `Literal[A]` and `Literal[B]`"
26+
reveal_type(A | B) # revealed: Unknown
27+
```

0 commit comments

Comments
 (0)