Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isinstance(foo, NoneType) does not narrow foo as None #14394

Closed
Jasha10 opened this issue Jan 4, 2023 · 2 comments
Closed

isinstance(foo, NoneType) does not narrow foo as None #14394

Jasha10 opened this issue Jan 4, 2023 · 2 comments
Labels
bug mypy got something wrong

Comments

@Jasha10
Copy link

Jasha10 commented Jan 4, 2023

Describe the bug
With a variable foo typed as T | None, the statement isinstance(foo, NoneType) does not narrow foo to be None.
Similarly, a match statement with a case NoneType() arm fails to narrow.

To Reproduce

# tmp.py
from random import getrandbits
from types import NoneType
from typing_extensions import assert_never

random_bool = bool(getrandbits(1))

foo: int | None = 123 if random_bool else None

if isinstance(foo, int):
    ...
elif isinstance(foo, NoneType):
    ...
else:
    assert_never(foo)
$ mypy tmp.py
tmp.py:15: error: Argument 1 to "assert_never" has incompatible type "None"; expected "NoReturn"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

I get an identical error using a match statement as below:

# match statement:
match foo:
    case int():
        ...
    case NoneType():
        ...
    case _:
        assert_never(foo)  # mypy error: Argument 1 to "assert_never" has incompatible type "None"; expected "NoReturn"  [arg-type]

Expected behavior
I would not expect mypy to give an error; I'd expect mypy to narrow foo as None in the second arm of the if-elif block above.

Additional context
I've opened a similar issue against pyright: microsoft/pyright#4402.

Environment

$ mypy --version
mypy 0.991 (compiled: yes)
$ python --version
Python 3.10.8
@Jasha10 Jasha10 added the bug mypy got something wrong label Jan 4, 2023
@Jasha10 Jasha10 changed the title isinstance(foo, NoneType) does not narrow foo as None isinstance(foo, NoneType) does not narrow foo as None Jan 4, 2023
@hauntsaninja
Copy link
Collaborator

Duplicate of #13154

@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Jan 4, 2023
@Jasha10
Copy link
Author

Jasha10 commented Jan 7, 2023

A workaround for the match statement example is to use case None:

match foo:
    case int():
        ...
    case None:  # use `None` instead of `NoneType()`
        ...
    case _:
        assert_never(foo)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

2 participants