Skip to content

mypy doesn't realize None is an instance of type(None) #9541

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

Closed
jwodder opened this issue Oct 7, 2020 · 2 comments
Closed

mypy doesn't realize None is an instance of type(None) #9541

jwodder opened this issue Oct 7, 2020 · 2 comments
Labels
feature priority-2-low topic-type-narrowing Conditional type narrowing / binder

Comments

@jwodder
Copy link

jwodder commented Oct 7, 2020

(I apologize if this has already been reported; searching the repository's issues for "type(None)" returns 554 open issues and 1438 closed issues, so you'll have to forgive me if I didn't check every one.)

Bug Report

Consider the following code:

from typing import Optional

def func(x: Optional[int]) -> int:
    if isinstance(x, type(None)):
        return 0
    else:
        return x + 1  # This is line 7

If mypy (either v0.782 or commit 6b0f7d7) is run on this code with the default settings, it fails with:

mypy02.py:7: error: Unsupported operand types for + ("None" and "int")
mypy02.py:7: note: Left operand is of type "Optional[int]"
Found 1 error in 1 file (checked 1 source file)

However, if the line if isinstance(x, type(None)): is replaced with if x is None:, the code passes mypy.

I believe mypy's current behavior is in error, as the only difference from the if x is None: version is that the type(None) version also catches hypothetical subtypes of None, which makes to difference to whether x will be int or not in the else: branch. In both versions, x in the else: branch should only be int, not Optional[int].

(Yes, I realize that writing isinstance(x, type(None)) is highly unusual, but this is simplified from more complex code that used an expression of the form isinstance(x, (int, type(None))) and still failed to type-check unless I rewrote it to isinstance(x, int) or x is None.)

Your Environment

  • Mypy version used: both version 0.782 and commit 6b0f7d7
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.8.5
  • Operating system and version: macOS 10.13.6
@jwodder jwodder added the bug mypy got something wrong label Oct 7, 2020
@hauntsaninja hauntsaninja added feature priority-2-low and removed bug mypy got something wrong labels Oct 13, 2020
@AlexWaygood AlexWaygood added the topic-type-narrowing Conditional type narrowing / binder label Apr 1, 2022
@finite-state-machine
Copy link

Possibly related to #13154?

Mypy-play.net link: https://mypy-play.net/?mypy=master&python=3.11&gist=c4a64da5bb1ada262a6a18805489f9ce

Can confirm this persists on master as of this date.

@tyralla
Copy link
Collaborator

tyralla commented Apr 4, 2024

@jwodder We implemented this in Mypy 1.9 (see @finite-state-machine's playground example) but I wasn't aware of this issue. I think it can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature priority-2-low topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

No branches or pull requests

6 participants