-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
I noticed a regression when switching from 0.720 to 0.730. Here's the code:
def f() -> int:
size = 2 ** 20
reveal_type(size)
return size
Expected behavior
With mypy 0.720 (no matter whether the new or the old semantic analyzer is used), I get:
$ mypy --strict f.py
f.py:3: note: Revealed type is 'builtins.int'
Actual behavior
With mypy 0.730 (Python 3.6.8), I get:
$ mypy --strict f.py
f.py:3: note: Revealed type is 'Any'
f.py:4: error: Returning Any from function declared to return "int"
Notes
The behavior from 0.720 is what I'd expect.
One thing I noticed is that the typeshed indeed declares that __pow__
for two int
s returns Any
. This makes sense because 2 ** -2
is a float
. The only recent change which I can see in the typeshed though is the following:
--- a/stdlib/2and3/builtins.pyi
+++ b/stdlib/2and3/builtins.pyi
@@ -168,7 +168,7 @@ class int:
def __rtruediv__(self, x: int) -> float: ...
def __rmod__(self, x: int) -> int: ...
def __rdivmod__(self, x: int) -> Tuple[int, int]: ...
- def __pow__(self, x: int) -> Any: ... # Return type can be int or float, depending on x.
+ def __pow__(self, __x: int, __modulo: Optional[int] = ...) -> Any: ... # Return type can be int or float, depending on x.
def __rpow__(self, x: int) -> Any: ...
def __and__(self, n: int) -> int: ...
(see: python/typeshed@b2cd972)
This means that the Any
return type has always been there but mypy
used to correctly recognize that 2 ** 20
is an int
. It's difficult for me to tell whether the behavior in 0.730 is a regression compared to 0.720 or actually the desired behavior – it seems to me that mypy
follows the typeshed more precisely here. However, maybe it's worth to handle literals like 2 ** 30
in a way that mypy
knows that this is always int
?