diff --git a/mypy/semanal.py b/mypy/semanal.py index af6ec9be8080..7d3ed113a886 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -847,7 +847,15 @@ def setup_class_def_analysis(self, defn: ClassDef) -> None: kind = MDEF if self.is_func_scope(): kind = LDEF - self.add_symbol(defn.name, SymbolTableNode(kind, defn.info), defn) + node = SymbolTableNode(kind, defn.info) + self.add_symbol(defn.name, node, defn) + if kind == LDEF: + # We need to preserve local classes, let's store them + # in globals under mangled unique names + local_name = defn.info._fullname + '@' + str(defn.line) + defn.info._fullname = self.cur_mod_id + '.' + local_name + defn.fullname = defn.info._fullname + self.globals[local_name] = node def analyze_base_classes(self, defn: ClassDef) -> None: """Analyze and set up base classes. diff --git a/test-data/unit/check-incremental.test b/test-data/unit/check-incremental.test index b4c5de57fb12..0ce740ac60ed 100644 --- a/test-data/unit/check-incremental.test +++ b/test-data/unit/check-incremental.test @@ -1768,6 +1768,53 @@ main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapp main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)' main:4: error: Revealed type is 'def () -> ntcrash.C.A@4' +[case testIncrementalInnerClassAttrInMethod] +import crash +nonexisting +[file crash.py] +class C: + def f(self) -> None: + class A: + pass + self.a = A() +[out1] +main:2: error: Name 'nonexisting' is not defined +[out2] +main:2: error: Name 'nonexisting' is not defined + +[case testIncrementalInnerClassAttrInMethodReveal] +import crash +reveal_type(crash.C().a) +reveal_type(crash.D().a) +[file crash.py] +from typing import TypeVar, Generic +T = TypeVar('T') +class C: + def f(self) -> None: + class A: + pass + self.a = A() +reveal_type(C().a) +class D: + def f(self) -> None: + class A: + def g(self) -> None: + class B(Generic[T]): + pass + self.b = B[int]() + self.a = A().b +reveal_type(D().a) +[out1] +tmp/crash.py:8: error: Revealed type is 'crash.A@5' +tmp/crash.py:17: error: Revealed type is 'crash.B@13[builtins.int*]' +main:2: error: Revealed type is 'crash.A@5' +main:3: error: Revealed type is 'crash.B@13[builtins.int*]' +[out2] +tmp/crash.py:8: error: Revealed type is 'crash.A@5' +tmp/crash.py:17: error: Revealed type is 'crash.B@13[builtins.int*]' +main:2: error: Revealed type is 'crash.A@5' +main:3: error: Revealed type is 'crash.B@13[builtins.int*]' + [case testGenericMethodRestoreMetaLevel] from typing import Dict diff --git a/test-data/unit/semanal-classes.test b/test-data/unit/semanal-classes.test index a99f8511ad0c..f292c303b862 100644 --- a/test-data/unit/semanal-classes.test +++ b/test-data/unit/semanal-classes.test @@ -315,7 +315,7 @@ MypyFile:1( A PassStmt:2()) ExpressionStmt:3( - NameExpr(A [l]))))) + NameExpr(A [__main__.A@2]))))) [case testReferenceToClassWithinClass] class A: @@ -364,7 +364,7 @@ MypyFile:1( AssignmentStmt:3( NameExpr(x [l]) NameExpr(None [builtins.None]) - A)))) + __main__.A@2)))) [case testAccessToLocalInOuterScopeWithinNestedClass] def f(x):