Shoobx / mypy-zope

Plugin for mypy to support zope.interface
MIT License
39 stars 13 forks source link

Mypy's `--warn-unreachable` option erroneously considers some `isinstance` calls to be always False with mypy-zope 0.9.0 #91

Open DMRobertson opened 1 year ago

DMRobertson commented 1 year ago

With mypy 1.0.0 and mypy-zope 0.9.0, the typechecker seems to think that that isinstance(x, T) is always false when T implements some interface Iand x: Optional[I]. For example, the source

from typing import Optional, reveal_type
from zope.interface import implementer, Interface

class IFoo(Interface):
    ...

@implementer(IFoo)
class MyFoo:
    ...

def make_foo() -> Optional[IFoo]:
    return MyFoo()

x = make_foo()
reveal_type(x)
assert isinstance(x, MyFoo)
print("hello")

yields

$ mypy temp.py
temp.py:19: note: Revealed type is "Union[temp.IFoo, None]"
temp.py:21: error: Statement is unreachable  [unreachable]
Found 1 error in 1 file (checked 1 source file)

but at runtime, we see that the print statement is reachable:

$ python temp.py
Runtime type is 'MyFoo'
hello

Would guess that #90 is related to this somehow.

kedder commented 1 year ago

Hm, but isn't it right though? There is no way for mypy to know if x is an instance of MyFoo. It is an instance of IFoo according to the description (or maybe None). It may be MyFoo, or any other implementation of IFoo.

DMRobertson commented 1 year ago

There is no way for mypy to know if x is an instance of MyFoo. It is an instance of IFoo according to the description (or maybe None). It may be MyFoo, or any other implementation of IFoo.

I agree with this. But mypy cannot conclude from this that isinstance(x, MyFoo) must be False in all circumstances---which is what I think leads to the unreachable error.

kedder commented 1 year ago

That's fair. I'll take to look.

DMRobertson commented 1 year ago

Many thanks! FWIW we've only seen this problem when checking our test, so it's not the end of the world as is!

kedder commented 1 year ago

It is strange, but I can't repro it - see #92. @DMRobertson are you using some special mypy configuration to trigger the problem?

DMRobertson commented 1 year ago

Ahh, sorry. I should have double-checked this with a clean environment.

I think you need the --warn-unreachable command line flag to see this behaviour. (I was using Synapse's mypy config which has this turned on by default.)