python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.52k stars 2.83k forks source link

int.__truediv__() accepted by Protocol that effectively requires that an int is returned #17110

Open Joshix-1 opened 7 months ago

Joshix-1 commented 7 months ago

Bug Report

Mypy allows type-unsafe code.

To Reproduce

https://mypy-play.net/?mypy=1.0.0&python=3.10&gist=ab7449de421b39046dadf9c022d82e77

from abc import abstractmethod
from typing import Protocol, TypeVar

from typing_extensions import reveal_type

T = TypeVar("T")

class SupportsSelfDivision(Protocol):

    @abstractmethod
    def __truediv__(self: T, other: int) -> T: ...

a: SupportsSelfDivision = 0  # ok (why?)

SSD = TypeVar("SSD", bound=SupportsSelfDivision)

def slash_1_000(x: SSD) -> SSD:
    return x / 1_000

reveal_type(slash_1_000(1))  # int (it's float at runtime!)
reveal_type(1 / 1_000)  # float

Expected Behavior

int should not satisfy SupportsSelfDivision. Runtime type should be the same as mypy reveals. Or there should be an error that int is not SupportsSelfDivision

Actual Behavior

int is SupportsSelfDivision. Mypy doesn't complain and says it's int even though it's float.

Your Environment

mypy Playground + local

finite-state-machine commented 6 months ago

@Joshix-1 to help get this triaged, I respectfully suggest changing the title of this bug to something more specific, e.g., "int.__truediv__() accepted by Protocol that effectively calls for Real numbers"

finite-state-machine commented 6 months ago

Somewhat related: #205