report unsafe operator type on subclasses
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 516
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the Bug
```py
class A:
def __add__(self, other: A) -> int:
return 1
class B(A):
def __radd__(self, other: A) -> str:
return "B"
def f(a1: A, a2: A):
x: int = a1 + a2
print(x) # static: int, runtime: "B"
f(A(), B())
```
here, the right hand subtype rule will be used, and `B.__radd__` will be called first, resulting in `"B"`, not `1`
if the supertype additionally defines a `__radd__`, then it can be incompatible with it's `__add__`, as all the information about the operation will be known
to ensure safety we must report when the subtypes `__radd__` in incompatable with the supertypes `__add__`, when the super type does not define a `__radd__`. but the right hand subtype rule complicates things...
so we should always form a union when the lower bound is not known:
```py
class A:
def __add__(self, other: object) -> int: ...
def __radd__(self, other: object) -> str: ...
def __sub__(self, other: object) -> int: ...
def __or__(self, other: object) -> int: ...
class B(A):
def __radd__(self, other: object) -> str: ... # no error, valid override of A.__radd__
def __rsub__(self, other: object) -> Literal[1]: ... # not error, compatiable with A.__add__
def __ror__(self, other: object) -> str: ... # error, incompatible with A.__or__
def f(a1: A = A(), a2: A = B()):
# when we don't know what `a2` is
a1 + a2 # static: int | str, runtime: str
# we definitely know that rhs is a subtype of lhs
A() + B() # static: str, runtime: str
# we definitely know that rhs is not a subtype of lhs
a1 + A() # static: int, runtime: int
```
# this also applies to inplace operators
```py
class A:
def __add__(self, other: A) -> int:
return 1
class B(A):
def __iadd__(self, other: A) -> str: # expect error: `__iadd__` must be compatable with `A.__add__`, as `A` does not define `__iadd__`
return "a"
def f(a1: A, a2: A):
a = a1
a += a2
print(a) # static: int, runtime: "a"
f(B(), A())
```
note that the righthand subtype rule applies after `__iadd__`, so this case is much more straightforward to support
### Sandbox Link
_No response_
### (Only applicable for extension issues) IDE Information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.