Closed Cnoor0171 closed 1 week ago
There's something wrong with this logic. When checking for narrowing in if
clause by is None
, we explicitly request to not consider bare TypeVar
overlapping with None
. The obvious decision is to stop asking for that, but... There's a test asserting this behaviour (introduced in #5476, and if
clause is indeed unreachable - using a non-trivial body gives an [unreachable]
diagnostic with --warn-unreachable
):
I don't think that this approach is sound: narrowing a lone TypeVar is a common problem, it shouldn't erroneously mark code as unreachable.
binder
builds a Union of types after all non-terminating branches when exiting a frame, so here it produces None | T
(None
from the if
clause since it's reachable, and T
from a pass-through).
I tried to modify the binder to keep track of whether every type in frame was updated via an isinstance
check or by assignment, and this seems to work as expected. I'm not sure, however, that this approach covers all corner cases. We already know that TypeVar + isinstance
causes a lot of pain (#9424 and many others), so this probably won't make things marginally worse.
Bug Report
Mypy doesn't seem to like it when you check if an argument with typevar type is checked to see if it is
None
. It incorrectly reportserror: Statement is unreachable [unreachable]
To Reproduce
https://mypy-play.net/?mypy=latest&python=3.12&flags=strict%2Cwarn-unreachable&gist=ceb8193f19f8b53a55dea70fad802469
Run mypy with
--warn-unreachable
flagExpected Behavior
No errors
Actual Behavior
The error seems to only happen when checking if arg is
None
, but not with other types. For example, I tired changingif arg is None:
line to the following and these were the results.if arg is True:
-> no errorsif isinstance(arg, int):
-> no errorsif isinstance(arg, type(None)):
-> unreachable errorif arg == None:
-> No errorAlso, changing the type to
T | None
removes the error as well.Your Environment
mypy.ini
(and other config files):warn_unreachable = True