[red-knot] Handle special case returning NotImplemented (#17034)
## Summary Closes #16661 This PR includes two changes: - `NotImplementedType` is now a member of `KnownClass` - We skip `is_assignable_to` checks for `NotImplemented` when checking return types ### Limitation ```py def f(cond: bool) -> int: return 1 if cond else NotImplemented ``` The implementation covers cases where `NotImplemented` appears inside a `Union`. However, for more complex types (ex. `Intersection`) it will not worked. In my opinion, supporting such complexity is unnecessary at this point. ## Test Plan Two `mdtest` files were updated: - `mdtest/function/return_type.md` - `mdtest/type_properties/is_singleton.md` To test `KnownClass`, run: ```bash cargo test -p red_knot_python_semantic -- types::class:: ```
This commit is contained in:
@@ -269,3 +269,45 @@ def f(cond: bool) -> int:
|
||||
if cond:
|
||||
return 2
|
||||
```
|
||||
|
||||
## NotImplemented
|
||||
|
||||
`NotImplemented` is a special symbol in Python. It is commonly used to control the fallback behavior
|
||||
of special dunder methods. You can find more details in the
|
||||
[documentation](https://docs.python.org/3/library/numbers.html#implementing-the-arithmetic-operations).
|
||||
|
||||
```py
|
||||
from __future__ import annotations
|
||||
|
||||
class A:
|
||||
def __add__(self, o: A) -> A:
|
||||
return NotImplemented
|
||||
```
|
||||
|
||||
However, as shown below, `NotImplemented` should not cause issues with the declared return type.
|
||||
|
||||
```py
|
||||
def f() -> int:
|
||||
return NotImplemented
|
||||
|
||||
def f(cond: bool) -> int:
|
||||
if cond:
|
||||
return 1
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def f(x: int) -> int | str:
|
||||
if x < 0:
|
||||
return -1
|
||||
elif x == 0:
|
||||
return NotImplemented
|
||||
else:
|
||||
return "test"
|
||||
|
||||
def f(cond: bool) -> str:
|
||||
return "hello" if cond else NotImplemented
|
||||
|
||||
def f(cond: bool) -> int:
|
||||
# error: [invalid-return-type] "Object of type `Literal["hello"]` is not assignable to return type `int`"
|
||||
return "hello" if cond else NotImplemented
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user