Description
Bug Report
builtins.float
and builtins.int
shouldn't be assignable to a Protocol
implementing hex: () -> str
, because that would be type-unsafe:
>>> int().hex()
Traceback (most recent call last):
File "<python-input-0>", line 1, in <module>
int().hex()
^^^^^^^^^
AttributeError: 'int' object has no attribute 'hex'
>>> bool().hex()
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
bool().hex()
^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'hex'
Mypy accepts this regardless.
To Reproduce
from typing import Protocol
class CanHex(Protocol):
def hex(self, /) -> str: ...
True negative:
float_has_hex: CanHex = 3.14 # accepted
True positives:
object_doesnt_have_hex: CanHex = object() # rejected: [assignment]
complex_doesnt_have_hex: CanHex = 1j # rejected: [assignment]
False negatives:
int_doesnt_have_hex: CanHex = 666 # accepted?
bool_clearly_also_doesnt_have_hex: CanHex = False # accepted??
https://mypy-play.net/?mypy=latest&python=3.12&gist=8ac210b6e647983b5c165af053ccd7d1
This isn't limited to .hex()
, but applies to all methods that are implemented by builtins.float
but not by builtins.int
.
I consider this a high-priority issue, because of the following reasons:
- It's type-unsafe, even in the most explicit of situations:
def tohex(x: CanHex): return x.hex()
- This issue, in combination with
float
andcomplex
forcibly change invariant types to covariant #18257, makes it impossible to distinguish betweenint
andfloat
input using static typing.
The second reason in particular is a big problem for NumPy, because it forces us to annotate e.g. np.dtype(complex)
as np.dtype[np.complex128 | np.float64 | np.int_ | np.bool]
, and np.array(3.14)
as np.ndarray[tuple[()], np.dtype[np.float64 | np.int_ | np.bool]]
.
So I'm sure you can see how this is confusing for users, especially if you consider that usually tends to propagate to other dtype- and array-types.
We can't use the "Any
trick" either, because that'd be problematic for functions that overload on dtype, of which there are many.