Description
While working on protocols, I noticed that stubs often use Any
where object
will be more appropriate and vice versa. Because of how protocol inference works and how current mypy solver works, this leads to problems since sometimes mypy infers Any
instead of giving an error (maybe we could improve this by "tightening" solver?)
I think the root of the problem is that wee don't have a good story about Any
. I believe the rules for interaction between Any
and other things should be like this (where C
is a normal class like int
or str
):
(1) join(Any, object) == object
(2) meet(Any, object) == Any
(3) join(Any, C) == C
(4) meet(Any, C) == C
(5) join(Any, NoReturn) == Any
(6) meet(Any, NoReturn) == NoReturn
I use NoReturn
for uninhabited type, since it is how it is currently called in PEP 484. The above rules could be summarized in a simple diagram:
object
|
Any (if it appears in a meet)
/ | \
... all other types ...
\ | /
Any (if it appear in a join)
|
NoReturn
Currently, mypy behaves in a completely different way, and I believe this is not right, let me explain why. We could focus on rules (3) and (4). Currently, mypy returns Any
in both these cases. Here is why it is not safe:
from typing import Any
x = 'a'
y: Any = 1
lst = [x, y]
lst[0] >> 1 # not detected by mypy, fails at runtime, will be fixed by rule (3)
def f(x: int) -> None:
x >> 1
def g(x: Any) -> None:
pass
funs = [f, g]
funs[0]('a') # not detected by mypy, fails at runtime, will be fixed by rule (4)
@JukkaL I will be grateful for your opinion.