Using numpy types conditionally gives confusing `[assignment]` error
Bug Report
When running strict mode on a simple example with numpy types, mypy will generate a confusing error message for [assignment] in which the expression type and the variable type are apparently the same, yet it fails anyway.
To Reproduce
import random
import numpy as np
def foo() -> None:
if random.randrange(2):
new_dtype = np.float16
else:
new_dtype = np.float32
Expected Behavior
If there is something wrong with the above code, I would expect mypy to tell me what the specific mismatch is.
Actual Behavior
$ mypy --strict repr.py
repr.py:9: error: Incompatible types in assignment (expression has type
"type[floating[Any]]", variable has type "type[floating[Any]]") [assignment]
new_dtype = np.float32
^~~~~~~~~~
Found 1 error in 1 file (checked 1 source file)
Why would type[floating[Any]] not match type[floating[Any]]?
Your Environment
- Mypy version used: mypy 1.9.0+dev.b956e6a57c4dd36d670097a3eccf7dc092348fec (compiled: no)
- Python version used: Python 3.11.3
In NumPy, numpy.floating serves as the base class for all floating-point numbers. When a variable is annotated with np.floating, its type becomes floating[Any].
float16 and float32 are aliases for floating[_16Bit] and floating[_32Bit] respectively in NumPy. This makes them incompatible with each other due to the different bit sizes.
To address this issue, I've revised the code as follows:
import random
import numpy as np
from numpy.typing import DTypeLike
def foo() -> None:
new_dtype: DTypeLike
if random.randrange(2):
new_dtype = np.float16
else:
new_dtype = np.float32
In this version, new_dtype is annotated with numpy.typing.DTypeLike, which is a type hint that encompasses all data types in NumPy, including np.float16 and np.float32. This change should resolve the type incompatibility issue.
float16andfloat32are aliases forfloating[_16Bit]andfloating[_32Bit]respectively in NumPy. This makes them incompatible with each other due to the different bit sizes.
That's a reasonable explanation, and I already had a solution for this in my code - but my concern is with the error from numpy that appears tautologically false. If mypy sees the type of np.float16 as type[floating[_16Bit]], it should communicate that to the user.