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

int inconsistently considered a subtype of float #17223

Closed
decorator-factory opened this issue May 7, 2024 · 2 comments
Closed

int inconsistently considered a subtype of float #17223

decorator-factory opened this issue May 7, 2024 · 2 comments
Labels
bug mypy got something wrong

Comments

@decorator-factory
Copy link

decorator-factory commented May 7, 2024

From PEP 484:

when an argument is annotated as having type float, an argument of type int is acceptable

So mypy considers this legal (mypy 1.10.0, with --strict):

def f(x: float) -> None:
    pass

f(42)

But when checking objects with isinstance, it thinks a variable annotated with float cannot be an int:

def f(x: float) -> None:
    if not isinstance(x, float):
        print("💀")  # error: Statement is unreachable  [unreachable]
        reveal_type(x)  # no diagnostics

f(42)

I think this is a bug, since float is always implicitly float | int. I'd expect mypy to not flag this as unreachable and reveal the type of x as int. (that's the behaviour pyright currently has)

Here's another potentially buggy example:

def f(x: float | str) -> None:
    if isinstance(x, float):
        reveal_type(x)  # Revealed type is "builtins.float"
    else:
        reveal_type(x)  # Revealed type is "builtins.str"

If you call this function as f(42), which mypy allows, the second branch will be selected at runtime.

@decorator-factory decorator-factory added the bug mypy got something wrong label May 7, 2024
@InSyncWithFoo
Copy link

InSyncWithFoo commented May 17, 2024

Another way to put it (playground):

from typing import Literal

a: int = 3

if isinstance(a, float):
   reveal_type(a)  # Never touched at runtime, but Mypy says `int`.

b: Literal[3] = 3

if isinstance(b, float):
   reveal_type(b)  # Never touched at runtime, correctly reported as unreachable.

@hauntsaninja
Copy link
Collaborator

Closing as a duplicate of #11516

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

3 participants