Skip to content

Commit

Permalink
Make TypeIndirectionVisitor depend on all classes in MROs (#4566)
Browse files Browse the repository at this point in the history
This fixes some nasty incremental mode bugs.
Fixes #4562.
  • Loading branch information
msullivan committed Feb 14, 2018
1 parent 2900fb6 commit c25dd08
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
6 changes: 5 additions & 1 deletion mypy/indirection.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ def visit_type_var(self, t: types.TypeVarType) -> Set[str]:
def visit_instance(self, t: types.Instance) -> Set[str]:
out = self._visit(*t.args)
if t.type is not None:
out.update(split_module_names(t.type.module_name))
# Uses of a class depend on everything in the MRO,
# as changes to classes in the MRO can add types to methods,
# change property types, change the MRO itself, etc.
for s in t.type.mro:
out.update(split_module_names(s.module_name))
return out

def visit_callable_type(self, t: types.CallableType) -> Set[str]:
Expand Down
73 changes: 73 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -3783,3 +3783,76 @@ import a
[out2]
main:2: error: Cannot find module named 'a'
main:2: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help)

[case testIncrementalInheritanceAddAnnotation]
# flags: --strict-optional
import a
[file a.py]
import b
def foo() -> None:
1 + b.Bar().get()
[file b.py]
from c import Baz
class Bar(Baz): pass

[file c.py]
class Baz:
def get(self):
return 1
[file c.py.2]
from typing import Optional
class Baz:
def get(self) -> Optional[int]:
return 1
[out]
[out2]
tmp/a.py:3: error: Unsupported operand types for + ("int" and "Optional[int]")


[case testIncrementalLotsOfInheritance]
import a
[file a.py]
from b import B
from d import D
def take(d: D) -> None: pass
def foo() -> None:
take(B())
[file b.py]
from c import C
class B(C): pass

[file c.py]
from d import D
class C(D): pass

[file c.py.2]
from d import D
class C: pass

[file d.py]
class D: pass
[out]
[out2]
tmp/a.py:5: error: Argument 1 to "take" has incompatible type "B"; expected "D"

[case testIncrementalInheritanceProperty]
import a
[file a.py]
import b
def foo() -> None:
1 + b.Bar().x
[file b.py]
from c import Baz
class Bar(Baz): pass

[file c.py]
class Baz:
def __init__(self):
self.x = 12 # type: int
[file c.py.2]
class Baz:
def __init__(self):
self.x = 'lol' # type: str
[out]
[out2]
tmp/a.py:3: error: Unsupported operand types for + ("int" and "str")

0 comments on commit c25dd08

Please sign in to comment.