Skip to content

Commit

Permalink
Don't serialize redefined symbol nodes (#7499)
Browse files Browse the repository at this point in the history
Redefined nodes sometimes have busted internal references (like a self
argument that has the class as its type even though it won't be able
to look it up) which can cause crashes. Since they can't have
references from outside themselves, we don't lose anything by not
serializing them.

Fixes a crash I observed at Dropbox.

This partially reverts #7413, which introduced this crash (while
fixing another), but leaves the test case it added.
  • Loading branch information
msullivan authored and JukkaL committed Sep 12, 2019
1 parent 8c17dd8 commit 99475b2
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 8 deletions.
8 changes: 2 additions & 6 deletions mypy/fixup.py
Expand Up @@ -57,12 +57,8 @@ def visit_type_info(self, info: TypeInfo) -> None:
if info.metaclass_type:
info.metaclass_type.accept(self.type_fixer)
if info._mro_refs:
# If the class is a "-redefinition", then its
# reference to itself might be busted, so just use the
# info instead of looking up the first element. Ew.
info.mro = [info] + [
lookup_qualified_typeinfo(self.modules, name, self.allow_missing)
for name in info._mro_refs[1:]]
info.mro = [lookup_qualified_typeinfo(self.modules, name, self.allow_missing)
for name in info._mro_refs]
info._mro_refs = None
finally:
self.current_info = save_info
Expand Down
2 changes: 0 additions & 2 deletions mypy/nodes.py
Expand Up @@ -2996,8 +2996,6 @@ def serialize(self, prefix: str, name: str) -> JsonDict:
fullname = self.node.fullname()
if (fullname is not None and '.' in fullname
and fullname != prefix + '.' + name
# If it only doesn't match because of -redefinition, that is OK
and fullname != prefix + '.' + name.split('-redefinition')[0]
and not (isinstance(self.node, Var)
and self.node.from_module_getattr)):
data['cross_ref'] = fullname
Expand Down
5 changes: 5 additions & 0 deletions mypy/semanal.py
Expand Up @@ -4245,6 +4245,11 @@ def add_redefinition(self,
redefinitions (such as e.g. variable redefined as a class).
"""
i = 1
# Don't serialize redefined nodes. They are likely to have
# busted internal references which can cause problems with
# serialization and they can't have any external references to
# them.
symbol.no_serialize = True
while True:
if i == 1:
new_name = '{}-redefinition'.format(name)
Expand Down
13 changes: 13 additions & 0 deletions test-data/unit/check-incremental.test
Expand Up @@ -5094,3 +5094,16 @@ tmp/a.py:4: error: Cannot determine type of 'foo'
[out2]
tmp/a.py:3: error: Cannot determine type of 'foo'
tmp/a.py:4: error: Cannot determine type of 'foo'

[case testRedefinitionClass]
import b
[file a.py]
from whatever import Foo # type: ignore

class Foo: # type: ignore
def f(self) -> None:
pass
[file b.py]
import a
[file b.py.2]
import a # a change

0 comments on commit 99475b2

Please sign in to comment.