diff --git a/mypy/fixup.py b/mypy/fixup.py index c9a45b890b92..09c190620241 100644 --- a/mypy/fixup.py +++ b/mypy/fixup.py @@ -57,8 +57,12 @@ def visit_type_info(self, info: TypeInfo) -> None: if info.metaclass_type: info.metaclass_type.accept(self.type_fixer) if info._mro_refs: - info.mro = [lookup_qualified_typeinfo(self.modules, name, self.allow_missing) - for name in 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_refs = None finally: self.current_info = save_info @@ -76,6 +80,7 @@ def visit_symbol_table(self, symtab: SymbolTable) -> None: stnode = lookup_qualified_stnode(self.modules, cross_ref, self.allow_missing) if stnode is not None: + assert stnode.node is not None value.node = stnode.node elif not self.allow_missing: assert stnode is not None, "Could not find cross-ref %s" % (cross_ref,) diff --git a/mypy/nodes.py b/mypy/nodes.py index 236cb92c9a0f..79343f4ad212 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2986,8 +2986,10 @@ def serialize(self, prefix: str, name: str) -> JsonDict: assert self.node is not None, '%s:%s' % (prefix, name) if prefix is not None: fullname = self.node.fullname() - if (fullname is not None and '.' in fullname and - fullname != prefix + '.' + name + 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 diff --git a/mypy/semanal.py b/mypy/semanal.py index df4126cbf30a..22da6c3b678d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3114,6 +3114,7 @@ def process_module_assignment(self, lvals: List[Lvalue], rval: Expression, # never create module alias except on initial var definition elif lval.is_inferred_def: lnode.kind = self.current_symbol_kind() + assert rnode.node is not None lnode.node = rnode.node def process__all__(self, s: AssignmentStmt) -> None: diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 551c752964c7..b55d765d4bce 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -9160,3 +9160,27 @@ Data = Tuple[User, File] [typing fixtures/typing-full.pyi] [out] == + +[case testClassRedef] +# An issue involved serializing these caused crashes in the past + +[file a.py] +class A: + pass + +x = 0 + +[file a.py.2] +class A: + a = A() + +x = '0' + +[file b.py] +from a import A, x + +class A: # type: ignore + pass + +[out] +==
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: