Closed
Description
Bug Report
Mypy is incoherent in the following code even though the only difference is the order of the isinstance
checks. I know that Optional is the idiomatic mypy way to represent possibly missing values, but this is the smallest example I found that shows the problem.
from dataclasses import dataclass
from typing import Generic, TypeVar, Union, NoReturn
def assert_never(a: NoReturn) -> NoReturn:
raise AssertionError("Unhandled type: {}".format(type(a).__name__))
@dataclass
class Nothing:
pass
T = TypeVar("T")
@dataclass
class Just(Generic[T]):
value: T
Maybe = Union[Nothing, Just[T]]
def ok(a: Maybe[int]) -> None:
if isinstance(a, Just):
print(a.value)
elif isinstance(a, Nothing):
print("nothing")
else:
assert_never(a)
def ko(a: Maybe[int]) -> None:
if isinstance(a, Nothing):
print("nothing")
elif isinstance(a, Just):
print(a.value)
else:
assert_never(a)
Expected Behavior
Either mypy finds an error in both functions or neither.
Actual Behavior
In the ko
function, mypy finds this error for the last line:
Argument 1 to "assert_never" has incompatible type "Just[int]"; expected "NoReturn"
If I use a concrete type instead of a generic one in the Just
class no error is reported in both functions.
Your Environment
- Mypy version used: 0.812
- Mypy command-line flags: N/A
- Mypy configuration options from
mypy.ini
(and other config files): N/A - Python version used: 3.9.2
- Operating system and version: N/A