From 8c61bb3d8e50141cef451842bff1e5963e5c8f6c Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 20:06:20 -0800 Subject: [PATCH 01/31] Fix class scoped imports Fixes #11045, fixes https://github.com/huggingface/transformers/issues/13390 Fixes #10488 Fixes #7045 Fixes #7806 Fixes #11641 Fixes #11351 Fixes #10488 Co-authored-by: @A5rocks --- mypy/semanal.py | 11 +++- test-data/unit/check-classes.test | 90 +++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 22d6b2e571ba..7c9d0bec413a 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4756,7 +4756,16 @@ def add_imported_symbol(self, module_hidden: bool) -> None: """Add an alias to an existing symbol through import.""" assert not module_hidden or not module_public - symbol = SymbolTableNode(node.kind, node.node, + + node_node = node.node + if self.is_class_scope() and isinstance(node_node, (FuncBase, Var)): + # Imports inside class scope do not produce methods. + # We construct a Var so as to treat them more like assignments. + node_node = Var(node_node.name, node_node.type) + assert self.type is not None + node_node.info = self.type + + symbol = SymbolTableNode(node.kind, node_node, module_public=module_public, module_hidden=module_hidden) self.add_symbol_table_node(name, symbol, context) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index a2bcdade3287..ad3cadae01f6 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7134,3 +7134,93 @@ class B(A): # E: Final class __main__.B has abstract attributes "foo" [case testUndefinedBaseclassInNestedClass] class C: class C1(XX): pass # E: Name "XX" is not defined + +[case testClassScopeImportFunction] +class Foo: + from mod import foo + +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo().foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +[file mod.py] +def foo(x: int, y: int) -> int: ... + +[case testClassScopeImportVariable] +class Foo: + from mod import foo + +reveal_type(Foo.foo) # N: Revealed type is "builtins.int" +reveal_type(Foo().foo) # N: Revealed type is "builtins.int" +[file mod.py] +foo: int + +[case testClassScopeImportModule] +class Foo: + import mod + +reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" +[file mod.py] +foo: int + +[case testClassScopeImportModuleStar] +class Foo: + from mod import * + +reveal_type(Foo.foo) # N: Revealed type is "builtins.int" +reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.baz) # E: "Type[Foo]" has no attribute "baz" \ + # N: Revealed type is "Any" +[file mod.py] +foo: int +def bar(x: int) -> int: ... + +[case testClassScopeImportFunctionNested] +class Foo: + class Bar: + from mod import baz + +reveal_type(Foo.Bar.baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.Bar().baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +[file mod.py] +def baz(x: int) -> int: ... + +[case testClassScopeImportUndefined] +class Foo: + from unknown import foo # E: Cannot find implementation or library stub for module named "unknown" \ + # N: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports + +reveal_type(Foo.foo) # N: Revealed type is "Any" +reveal_type(Foo().foo) # N: Revealed type is "Any" + +[case testClassScopeImportWithFollowImports] +# flags: --follow-imports=skip +class Foo: + from mod import foo + +reveal_type(Foo().foo) # N: Revealed type is "Any" +[file mod.py] +def foo(x: int, y: int) -> int: ... + +[case testClassScopeImportVarious] +class Foo: + from mod1 import foo + from mod2 import foo # E: Name "foo" already defined (possibly by an import) + + from mod1 import meth1 + def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined (possibly by an import) + + def meth2(self, a: str) -> str: ... + from mod1 import meth2 # E: Name "meth2" already defined on line 8 + +class Bar: + from mod1 import foo + +import mod1 +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Bar.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(mod1.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +[file mod1.py] +def foo(x: int, y: int) -> int: ... +def meth1(x: int) -> int: ... +def meth2(x: int) -> int: ... +[file mod2.py] +def foo(z: str) -> int: ... From c92c1722dd1552c7cb4c97bb1bdd74f762d7f4b4 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 20:11:32 -0800 Subject: [PATCH 02/31] fix import --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 1d0bac976f35..1b1d5af377ed 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -78,7 +78,7 @@ typing_extensions_aliases, EnumCallExpr, RUNTIME_PROTOCOL_DECOS, FakeExpression, Statement, AssignmentExpr, ParamSpecExpr, EllipsisExpr, TypeVarLikeExpr, implicit_module_attrs, - MatchStmt, + MatchStmt, FuncBase ) from mypy.patterns import ( AsPattern, OrPattern, ValuePattern, SequencePattern, From 3ebfda39d8026562825b350b7dbc62783c0c07c8 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 21:01:53 -0800 Subject: [PATCH 03/31] fix for mypyc --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 1b1d5af377ed..2f4348e7fd9f 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4787,7 +4787,7 @@ def add_imported_symbol(self, """Add an alias to an existing symbol through import.""" assert not module_hidden or not module_public - node_node = node.node + node_node: Optional[SymbolNode] = node.node if self.is_class_scope() and isinstance(node_node, (FuncBase, Var)): # Imports inside class scope do not produce methods. # We construct a Var so as to treat them more like assignments. From 63f8634eb1d33c554d46bdf554f0b8418c5c57fc Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 21:28:50 -0800 Subject: [PATCH 04/31] fix more tests --- mypy/semanal.py | 27 +++++++++++++++++++-------- test-data/unit/check-classes.test | 16 ++++++++++++++++ test-data/unit/semanal-modules.test | 2 +- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 2f4348e7fd9f..b89e11c3fe43 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4787,15 +4787,26 @@ def add_imported_symbol(self, """Add an alias to an existing symbol through import.""" assert not module_hidden or not module_public - node_node: Optional[SymbolNode] = node.node - if self.is_class_scope() and isinstance(node_node, (FuncBase, Var)): - # Imports inside class scope do not produce methods. - # We construct a Var so as to treat them more like assignments. - node_node = Var(node_node.name, node_node.type) - assert self.type is not None - node_node.info = self.type + symbol_node: Optional[SymbolNode] = node.node + if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): + # We construct a new node to represent this symbol and set its `info` attribute + # to `self.type`. Note that imports inside class scope do not produce methods, so + # in all cases constructing a Var gets us the assignment like behaviour we want. + existing = self.current_symbol_table().get(name) + if ( + existing is not None + and isinstance(existing.node, Var) + and existing.type == symbol_node.type + ): + # The redefinition checks in `add_symbol_table_node` don't work for our + # constructed Var, so check for possible redefinitions here. + symbol_node = existing.node + else: + symbol_node = Var(symbol_node.name, symbol_node.type) + assert self.type is not None + symbol_node.info = self.type - symbol = SymbolTableNode(node.kind, node_node, + symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, module_hidden=module_hidden) self.add_symbol_table_node(name, symbol, context) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index ad3cadae01f6..edc97af94197 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7161,6 +7161,22 @@ reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" [file mod.py] foo: int +[case testClassScopeImportFunctionAlias] +class Foo: + from mod import foo + bar = foo + + from mod import const_foo + const_bar = const_foo + +reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo.bar) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo.const_foo) # N: Revealed type is "builtins.int" +reveal_type(Foo.const_bar) # N: Revealed type is "builtins.int" +[file mod.py] +def foo(x: int, y: int) -> int: ... +const_foo: int + [case testClassScopeImportModuleStar] class Foo: from mod import * diff --git a/test-data/unit/semanal-modules.test b/test-data/unit/semanal-modules.test index 86bb82d7bd69..84f553ea8b5f 100644 --- a/test-data/unit/semanal-modules.test +++ b/test-data/unit/semanal-modules.test @@ -568,7 +568,7 @@ MypyFile:1( ImportFrom:2(_x, [y]) AssignmentStmt:3( NameExpr(z* [m]) - NameExpr(y [_x.y])))) + NameExpr(y [None])))) [case testImportInClassBody2] class A: From aa2457e6a260f8a843aba427e4e79085e598f9f4 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 21:35:26 -0800 Subject: [PATCH 05/31] fix even more tests --- mypy/semanal.py | 1 + test-data/unit/semanal-modules.test | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index b89e11c3fe43..7b379e1801b1 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4805,6 +4805,7 @@ def add_imported_symbol(self, symbol_node = Var(symbol_node.name, symbol_node.type) assert self.type is not None symbol_node.info = self.type + symbol_node._fullname = self.qualified_name(name) symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, diff --git a/test-data/unit/semanal-modules.test b/test-data/unit/semanal-modules.test index 84f553ea8b5f..16b9a9b18250 100644 --- a/test-data/unit/semanal-modules.test +++ b/test-data/unit/semanal-modules.test @@ -568,7 +568,7 @@ MypyFile:1( ImportFrom:2(_x, [y]) AssignmentStmt:3( NameExpr(z* [m]) - NameExpr(y [None])))) + NameExpr(y [__main__.A.y])))) [case testImportInClassBody2] class A: From 80b61091c18ee4e336faa0bdc854d31b082ea3b0 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 22:21:00 -0800 Subject: [PATCH 06/31] mypyc shot in the dark --- mypy/semanal.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 7b379e1801b1..327cbd6c202c 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4788,7 +4788,10 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node - if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): + if self.is_class_scope() and ( + # maybe mypyc likes this code better if we split up isinstance + isinstance(symbol_node, Var) or isinstance(symbol_node, FuncBase) + ): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. From 6eedcc43edda0feead00d0ee3262bd87fea9e032 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 22:42:36 -0800 Subject: [PATCH 07/31] Revert "mypyc shot in the dark" This reverts commit 80b61091c18ee4e336faa0bdc854d31b082ea3b0. --- mypy/semanal.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 327cbd6c202c..7b379e1801b1 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4788,10 +4788,7 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node - if self.is_class_scope() and ( - # maybe mypyc likes this code better if we split up isinstance - isinstance(symbol_node, Var) or isinstance(symbol_node, FuncBase) - ): + if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. From 7aa37cdf370e03645c7ba9f97e96192be5f6c327 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 22:43:33 -0800 Subject: [PATCH 08/31] mypyc shot in the dark pt 2 --- mypy/semanal.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 7b379e1801b1..c0ac5cc46042 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4788,7 +4788,7 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node - if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): + if self.is_class_scope() and isinstance(symbol_node, (Var, FuncBase)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. @@ -4802,7 +4802,12 @@ def add_imported_symbol(self, # constructed Var, so check for possible redefinitions here. symbol_node = existing.node else: - symbol_node = Var(symbol_node.name, symbol_node.type) + # Dumb if statement to appease mypyc + if isinstance(symbol_node, Var): + symbol_node = Var(symbol_node.name, symbol_node.type) + else: + symbol_node = Var(symbol_node.name, symbol_node.type) + assert self.type is not None symbol_node.info = self.type symbol_node._fullname = self.qualified_name(name) From cc550230e3e46bf5e79519c96c6d065bbb3a1f0d Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Wed, 19 Jan 2022 23:07:20 -0800 Subject: [PATCH 09/31] monkeys on a typewriter --- mypy/semanal.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index c0ac5cc46042..1e11052f3618 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4796,7 +4796,11 @@ def add_imported_symbol(self, if ( existing is not None and isinstance(existing.node, Var) - and existing.type == symbol_node.type + # Dumb clause to appease mypyc + and ( + (isinstance(symbol_node, Var) and existing.type == symbol_node.type) + or (isinstance(symbol_node, FuncBase) and existing.type == symbol_node.type) + ) ): # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var, so check for possible redefinitions here. From 037ce8ca3c1c3bf8febea3ba2cb16bd407c9a582 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Thu, 20 Jan 2022 00:17:36 -0800 Subject: [PATCH 10/31] Revert "monkeys on a typewriter" This reverts commit cc550230e3e46bf5e79519c96c6d065bbb3a1f0d. --- mypy/semanal.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 1e11052f3618..c0ac5cc46042 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4796,11 +4796,7 @@ def add_imported_symbol(self, if ( existing is not None and isinstance(existing.node, Var) - # Dumb clause to appease mypyc - and ( - (isinstance(symbol_node, Var) and existing.type == symbol_node.type) - or (isinstance(symbol_node, FuncBase) and existing.type == symbol_node.type) - ) + and existing.type == symbol_node.type ): # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var, so check for possible redefinitions here. From 2629040e8bf1956184de8f00c5135d385534c1ed Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Thu, 20 Jan 2022 00:17:42 -0800 Subject: [PATCH 11/31] Revert "mypyc shot in the dark pt 2" This reverts commit 7aa37cdf370e03645c7ba9f97e96192be5f6c327. --- mypy/semanal.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index c0ac5cc46042..7b379e1801b1 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4788,7 +4788,7 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node - if self.is_class_scope() and isinstance(symbol_node, (Var, FuncBase)): + if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. @@ -4802,12 +4802,7 @@ def add_imported_symbol(self, # constructed Var, so check for possible redefinitions here. symbol_node = existing.node else: - # Dumb if statement to appease mypyc - if isinstance(symbol_node, Var): - symbol_node = Var(symbol_node.name, symbol_node.type) - else: - symbol_node = Var(symbol_node.name, symbol_node.type) - + symbol_node = Var(symbol_node.name, symbol_node.type) assert self.type is not None symbol_node.info = self.type symbol_node._fullname = self.qualified_name(name) From 5615fc1a69d7d428527c416149ddb9c32eca44de Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Thu, 20 Jan 2022 00:19:38 -0800 Subject: [PATCH 12/31] lie to mypyc --- mypy/semanal.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 7b379e1801b1..0874e7a9ecc5 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -51,7 +51,7 @@ from contextlib import contextmanager from typing import ( - List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable + Any, List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable ) from typing_extensions import Final, TypeAlias as _TypeAlias @@ -4793,16 +4793,18 @@ def add_imported_symbol(self, # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. existing = self.current_symbol_table().get(name) + # I promise this type checks; I'm just making mypyc issues go away. + symbol_node_any: Any = cast(Any, symbol_node) if ( + # The redefinition checks in `add_symbol_table_node` don't work for our + # constructed Var, so check for possible redefinitions here. existing is not None and isinstance(existing.node, Var) - and existing.type == symbol_node.type + and existing.type == symbol_node_any.type ): - # The redefinition checks in `add_symbol_table_node` don't work for our - # constructed Var, so check for possible redefinitions here. symbol_node = existing.node else: - symbol_node = Var(symbol_node.name, symbol_node.type) + symbol_node = Var(symbol_node_any.name, symbol_node_any.type) assert self.type is not None symbol_node.info = self.type symbol_node._fullname = self.qualified_name(name) From a14004e56784c5cf63724c062e53229ee9426d87 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Thu, 20 Jan 2022 00:37:23 -0800 Subject: [PATCH 13/31] wow mypyc --- mypy/semanal.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0874e7a9ecc5..5c79a629ae70 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4788,13 +4788,15 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node + # I promise this type checks; I'm just making mypyc issues go away. + # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, + # when it can also be a FuncBase. + symbol_node_any: Any = cast(Any, symbol_node) if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so # in all cases constructing a Var gets us the assignment like behaviour we want. existing = self.current_symbol_table().get(name) - # I promise this type checks; I'm just making mypyc issues go away. - symbol_node_any: Any = cast(Any, symbol_node) if ( # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var, so check for possible redefinitions here. From 2119c3d2db0cf42400dc9ab1996a8a1ff3e3a131 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 02:27:25 -0800 Subject: [PATCH 14/31] Fix self binding and improve line number diagnostics --- mypy/semanal.py | 16 ++++++++++------ test-data/unit/check-classes.test | 10 ++++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 5c79a629ae70..ef88c07a8982 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -48,6 +48,7 @@ reduce memory use). """ +import copy from contextlib import contextmanager from typing import ( @@ -4788,10 +4789,6 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node - # I promise this type checks; I'm just making mypyc issues go away. - # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, - # when it can also be a FuncBase. - symbol_node_any: Any = cast(Any, symbol_node) if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so @@ -4802,12 +4799,19 @@ def add_imported_symbol(self, # constructed Var, so check for possible redefinitions here. existing is not None and isinstance(existing.node, Var) - and existing.type == symbol_node_any.type + and existing.type == symbol_node.type ): symbol_node = existing.node else: - symbol_node = Var(symbol_node_any.name, symbol_node_any.type) + if isinstance(symbol_node, Var): + symbol_node = Var(symbol_node.name, symbol_node.type) + elif isinstance(symbol_node, FuncBase): + symbol_node = copy.copy(symbol_node) + else: + assert False assert self.type is not None + symbol_node.line = context.line + symbol_node.column = context.column symbol_node.info = self.type symbol_node._fullname = self.qualified_name(name) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index edc97af94197..2748eb87c6b2 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7140,7 +7140,8 @@ class Foo: from mod import foo reveal_type(Foo.foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" -reveal_type(Foo().foo) # N: Revealed type is "def (x: builtins.int, y: builtins.int) -> builtins.int" +reveal_type(Foo().foo) # E: Invalid self argument "Foo" to attribute function "foo" with type "Callable[[int, int], int]" \ + # N: Revealed type is "def (y: builtins.int) -> builtins.int" [file mod.py] def foo(x: int, y: int) -> int: ... @@ -7195,7 +7196,8 @@ class Foo: from mod import baz reveal_type(Foo.Bar.baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" -reveal_type(Foo.Bar().baz) # N: Revealed type is "def (x: builtins.int) -> builtins.int" +reveal_type(Foo.Bar().baz) # E: Invalid self argument "Bar" to attribute function "baz" with type "Callable[[int], int]" \ + # N: Revealed type is "def () -> builtins.int" [file mod.py] def baz(x: int) -> int: ... @@ -7219,10 +7221,10 @@ def foo(x: int, y: int) -> int: ... [case testClassScopeImportVarious] class Foo: from mod1 import foo - from mod2 import foo # E: Name "foo" already defined (possibly by an import) + from mod2 import foo # E: Name "foo" already defined on line 2 from mod1 import meth1 - def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined (possibly by an import) + def meth1(self, a: str) -> str: ... # E: Name "meth1" already defined on line 5 def meth2(self, a: str) -> str: ... from mod1 import meth2 # E: Name "meth2" already defined on line 8 From e09bc0245d4b6f30595613ad69f80df6bbeed285 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 02:30:47 -0800 Subject: [PATCH 15/31] no more Any --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index ef88c07a8982..c3bd771d5723 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -52,7 +52,7 @@ from contextlib import contextmanager from typing import ( - Any, List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable + List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable ) from typing_extensions import Final, TypeAlias as _TypeAlias From b93491a7795b5b33400d3f269715cb286a3fab74 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 12:57:17 -0800 Subject: [PATCH 16/31] Fix various tests --- mypy/semanal.py | 2 +- test-data/unit/check-modules.test | 4 ++-- test-data/unit/check-newsemanal.test | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index c3bd771d5723..4e91ac880419 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4798,7 +4798,7 @@ def add_imported_symbol(self, # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var, so check for possible redefinitions here. existing is not None - and isinstance(existing.node, Var) + and isinstance(existing.node, (FuncBase, Var)) and existing.type == symbol_node.type ): symbol_node = existing.node diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 4f0aa83912ea..e708ee520497 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -131,9 +131,9 @@ def f() -> None: pass [case testImportWithinClassBody2] import typing class C: - from m import f + from m import f # E: Method must have at least one argument f() - f(C) # E: Too many arguments for "f" + f(C) # E: Too many arguments for "f" of "C" [file m.py] def f() -> None: pass [out] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 8a039ad278f3..276f634df9e4 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -2722,7 +2722,7 @@ import m [file m.py] class C: - from mm import f + from mm import f # E: Method must have at least one argument @dec(f) def m(self): pass @@ -2742,7 +2742,7 @@ import m [file m/__init__.py] class C: - from m.m import f + from m.m import f # E: Method must have at least one argument @dec(f) def m(self): pass From 7bd60db5f2424100de8c8d8c4e725ecc74d61cf3 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 15:02:12 -0800 Subject: [PATCH 17/31] make mypyc issues go away --- mypy/semanal.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 4e91ac880419..710fbf6b8f39 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -52,7 +52,7 @@ from contextlib import contextmanager from typing import ( - List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable + Any, List, Dict, Set, Tuple, cast, TypeVar, Union, Optional, Callable, Iterator, Iterable ) from typing_extensions import Final, TypeAlias as _TypeAlias @@ -4789,6 +4789,11 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node + # I promise this type checks; I'm just making mypyc issues go away. + # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, + # when it can also be a FuncBase. + # See also https://github.com/mypyc/mypyc/issues/892 + symbol_node_any: Any = cast(Any, symbol_node) if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. Note that imports inside class scope do not produce methods, so @@ -4799,14 +4804,14 @@ def add_imported_symbol(self, # constructed Var, so check for possible redefinitions here. existing is not None and isinstance(existing.node, (FuncBase, Var)) - and existing.type == symbol_node.type + and existing.type == symbol_node_any.type ): symbol_node = existing.node else: if isinstance(symbol_node, Var): - symbol_node = Var(symbol_node.name, symbol_node.type) + symbol_node = Var(symbol_node_any.name, symbol_node_any.type) elif isinstance(symbol_node, FuncBase): - symbol_node = copy.copy(symbol_node) + symbol_node = copy.copy(symbol_node_any) else: assert False assert self.type is not None From c46739995177126a5d3289798ead21e1919148bd Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 15:30:11 -0800 Subject: [PATCH 18/31] more mypyc --- mypy/semanal.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 710fbf6b8f39..22de1106d7c3 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4808,10 +4808,11 @@ def add_imported_symbol(self, ): symbol_node = existing.node else: - if isinstance(symbol_node, Var): + if isinstance(symbol_node_any, Var): symbol_node = Var(symbol_node_any.name, symbol_node_any.type) - elif isinstance(symbol_node, FuncBase): - symbol_node = copy.copy(symbol_node_any) + elif isinstance(symbol_node_any, FuncBase): + # Need to cast here as a side effect of the cast for mypyc above + symbol_node = cast(Any, copy.copy(symbol_node_any)) else: assert False assert self.type is not None From 1dc469d4ce176ea8caf6f4e61059b400e44d1a66 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 15:37:20 -0800 Subject: [PATCH 19/31] comment --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 22de1106d7c3..19c95c66fa0e 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4815,7 +4815,7 @@ def add_imported_symbol(self, symbol_node = cast(Any, copy.copy(symbol_node_any)) else: assert False - assert self.type is not None + assert self.type is not None # guaranteed by is_class_scope symbol_node.line = context.line symbol_node.column = context.column symbol_node.info = self.type From 4f32a01d845872cce02942a99f3723d42b38bca9 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 15:38:11 -0800 Subject: [PATCH 20/31] update comments --- mypy/semanal.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 19c95c66fa0e..3de49e23f788 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4796,12 +4796,11 @@ def add_imported_symbol(self, symbol_node_any: Any = cast(Any, symbol_node) if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): # We construct a new node to represent this symbol and set its `info` attribute - # to `self.type`. Note that imports inside class scope do not produce methods, so - # in all cases constructing a Var gets us the assignment like behaviour we want. + # to `self.type`. existing = self.current_symbol_table().get(name) if ( # The redefinition checks in `add_symbol_table_node` don't work for our - # constructed Var, so check for possible redefinitions here. + # constructed Var / FuncBase, so check for possible redefinitions here. existing is not None and isinstance(existing.node, (FuncBase, Var)) and existing.type == symbol_node_any.type From 6d027622743d3c48070e62d090e409840b25c167 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 16:19:39 -0800 Subject: [PATCH 21/31] fix type checking --- mypy/semanal.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 3de49e23f788..bce19af26053 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4798,6 +4798,7 @@ def add_imported_symbol(self, # We construct a new node to represent this symbol and set its `info` attribute # to `self.type`. existing = self.current_symbol_table().get(name) + node_to_add: Union[FuncBase, Var] if ( # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var / FuncBase, so check for possible redefinitions here. @@ -4805,20 +4806,22 @@ def add_imported_symbol(self, and isinstance(existing.node, (FuncBase, Var)) and existing.type == symbol_node_any.type ): - symbol_node = existing.node + node_to_add = existing.node else: if isinstance(symbol_node_any, Var): - symbol_node = Var(symbol_node_any.name, symbol_node_any.type) + node_to_add = Var(symbol_node_any.name, symbol_node_any.type) elif isinstance(symbol_node_any, FuncBase): - # Need to cast here as a side effect of the cast for mypyc above - symbol_node = cast(Any, copy.copy(symbol_node_any)) + node_to_add = copy.copy(symbol_node_any) else: assert False assert self.type is not None # guaranteed by is_class_scope - symbol_node.line = context.line - symbol_node.column = context.column - symbol_node.info = self.type - symbol_node._fullname = self.qualified_name(name) + node_to_add.line = context.line + node_to_add.column = context.column + node_to_add.info = self.type + node_to_add._fullname = self.qualified_name(name) + + assert isinstance(node_to_add, SymbolNode) + symbol_node = node_to_add symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, From 02dd54e8ed1d298a3cbee4ebed945c71674c17a4 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 16:21:13 -0800 Subject: [PATCH 22/31] comments --- mypy/semanal.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index bce19af26053..0d42b955e38a 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4789,14 +4789,15 @@ def add_imported_symbol(self, assert not module_hidden or not module_public symbol_node: Optional[SymbolNode] = node.node + # I promise this type checks; I'm just making mypyc issues go away. # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, # when it can also be a FuncBase. # See also https://github.com/mypyc/mypyc/issues/892 symbol_node_any: Any = cast(Any, symbol_node) if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): - # We construct a new node to represent this symbol and set its `info` attribute - # to `self.type`. + # For imports in class scope, we construct a new node to represent the symbol and set + # its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) node_to_add: Union[FuncBase, Var] if ( @@ -4808,6 +4809,7 @@ def add_imported_symbol(self, ): node_to_add = existing.node else: + # Construct the new node if isinstance(symbol_node_any, Var): node_to_add = Var(symbol_node_any.name, symbol_node_any.type) elif isinstance(symbol_node_any, FuncBase): From 4523607f390a587db2f626882fd29d70cff8cff5 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 16:49:50 -0800 Subject: [PATCH 23/31] more mypyc --- mypy/semanal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0d42b955e38a..8f549f00a625 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4799,7 +4799,7 @@ def add_imported_symbol(self, # For imports in class scope, we construct a new node to represent the symbol and set # its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) - node_to_add: Union[FuncBase, Var] + node_to_add: Any # Union[FuncBase, Var] if ( # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var / FuncBase, so check for possible redefinitions here. @@ -4822,8 +4822,8 @@ def add_imported_symbol(self, node_to_add.info = self.type node_to_add._fullname = self.qualified_name(name) - assert isinstance(node_to_add, SymbolNode) symbol_node = node_to_add + assert isinstance(symbol_node, SymbolNode) symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, From e71c1913568eecb2cfc66f80ddde7e53e4af33f5 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 17:07:06 -0800 Subject: [PATCH 24/31] i'm stuck in mypyc hell --- mypy/semanal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8f549f00a625..6d77f878f97d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4807,11 +4807,11 @@ def add_imported_symbol(self, and isinstance(existing.node, (FuncBase, Var)) and existing.type == symbol_node_any.type ): - node_to_add = existing.node + node_to_add = cast(Any, existing.node) else: # Construct the new node if isinstance(symbol_node_any, Var): - node_to_add = Var(symbol_node_any.name, symbol_node_any.type) + node_to_add = cast(Any, Var(symbol_node_any.name, symbol_node_any.type)) elif isinstance(symbol_node_any, FuncBase): node_to_add = copy.copy(symbol_node_any) else: From d5d80bd339739e11927f60e592bf08622c21bf3e Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 17:08:04 -0800 Subject: [PATCH 25/31] actually do this instead --- mypy/semanal.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 6d77f878f97d..c20fce59868d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4810,12 +4810,7 @@ def add_imported_symbol(self, node_to_add = cast(Any, existing.node) else: # Construct the new node - if isinstance(symbol_node_any, Var): - node_to_add = cast(Any, Var(symbol_node_any.name, symbol_node_any.type)) - elif isinstance(symbol_node_any, FuncBase): - node_to_add = copy.copy(symbol_node_any) - else: - assert False + node_to_add = copy.copy(symbol_node_any) assert self.type is not None # guaranteed by is_class_scope node_to_add.line = context.line node_to_add.column = context.column From 13f9e5f266e5f6509d3d0991705d9a5eaa810d5c Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 17:53:57 -0800 Subject: [PATCH 26/31] mypyc take 9000 --- mypy/semanal.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index c20fce59868d..3f4606d2cd35 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4792,33 +4792,30 @@ def add_imported_symbol(self, # I promise this type checks; I'm just making mypyc issues go away. # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, - # when it can also be a FuncBase. + # when it can also be a FuncBase. Once fixed, the casts in the following can be removed. # See also https://github.com/mypyc/mypyc/issues/892 - symbol_node_any: Any = cast(Any, symbol_node) - if self.is_class_scope() and isinstance(symbol_node, (FuncBase, Var)): + if self.is_class_scope() and isinstance((lambda x: x)(symbol_node), (FuncBase, Var)): + assert isinstance(symbol_node, SymbolNode) # For imports in class scope, we construct a new node to represent the symbol and set # its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) - node_to_add: Any # Union[FuncBase, Var] if ( # The redefinition checks in `add_symbol_table_node` don't work for our # constructed Var / FuncBase, so check for possible redefinitions here. existing is not None and isinstance(existing.node, (FuncBase, Var)) - and existing.type == symbol_node_any.type + and existing.type == cast(Any, symbol_node).type ): - node_to_add = cast(Any, existing.node) + symbol_node = existing.node else: # Construct the new node - node_to_add = copy.copy(symbol_node_any) + constructed_node = cast(Any, copy.copy(symbol_node)) assert self.type is not None # guaranteed by is_class_scope - node_to_add.line = context.line - node_to_add.column = context.column - node_to_add.info = self.type - node_to_add._fullname = self.qualified_name(name) - - symbol_node = node_to_add - assert isinstance(symbol_node, SymbolNode) + constructed_node.line = context.line + constructed_node.column = context.column + constructed_node.info = self.type + constructed_node._fullname = self.qualified_name(name) + symbol_node = constructed_node symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, From 08ea1a923119056afc42087fa18644c4e5c38aba Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 18:35:32 -0800 Subject: [PATCH 27/31] another cast --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 3f4606d2cd35..299fed891e69 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4806,7 +4806,7 @@ def add_imported_symbol(self, and isinstance(existing.node, (FuncBase, Var)) and existing.type == cast(Any, symbol_node).type ): - symbol_node = existing.node + symbol_node = cast(SymbolNode, existing.node) else: # Construct the new node constructed_node = cast(Any, copy.copy(symbol_node)) From 6f04070077a88cbe9dca0afce57c072d7e1ab5d1 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 19:16:20 -0800 Subject: [PATCH 28/31] fffff --- mypy/semanal.py | 54 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 6c2fabd33ef1..b3bf89733546 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4806,32 +4806,34 @@ def add_imported_symbol(self, symbol_node: Optional[SymbolNode] = node.node - # I promise this type checks; I'm just making mypyc issues go away. - # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, - # when it can also be a FuncBase. Once fixed, the casts in the following can be removed. - # See also https://github.com/mypyc/mypyc/issues/892 - if self.is_class_scope() and isinstance((lambda x: x)(symbol_node), (FuncBase, Var)): - assert isinstance(symbol_node, SymbolNode) - # For imports in class scope, we construct a new node to represent the symbol and set - # its `info` attribute to `self.type`. - existing = self.current_symbol_table().get(name) - if ( - # The redefinition checks in `add_symbol_table_node` don't work for our - # constructed Var / FuncBase, so check for possible redefinitions here. - existing is not None - and isinstance(existing.node, (FuncBase, Var)) - and existing.type == cast(Any, symbol_node).type - ): - symbol_node = cast(SymbolNode, existing.node) - else: - # Construct the new node - constructed_node = cast(Any, copy.copy(symbol_node)) - assert self.type is not None # guaranteed by is_class_scope - constructed_node.line = context.line - constructed_node.column = context.column - constructed_node.info = self.type - constructed_node._fullname = self.qualified_name(name) - symbol_node = constructed_node + if self.is_class_scope(): + # I promise this type checks; I'm just making mypyc issues go away. + # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, + # when it can also be a FuncBase. Once fixed, casts in the following can be removed. + # See also https://github.com/mypyc/mypyc/issues/892 + f = cast(Any, lambda x: x) + if isinstance(f(symbol_node), (FuncBase, Var)): + assert symbol_node is not None + # For imports in class scope, we construct a new node to represent the symbol and set + # its `info` attribute to `self.type`. + existing = self.current_symbol_table().get(name) + if ( + # The redefinition checks in `add_symbol_table_node` don't work for our + # constructed Var / FuncBase, so check for possible redefinitions here. + existing is not None + and isinstance(f(existing.node), (FuncBase, Var)) + and f(existing.type) == f(symbol_node).type + ): + symbol_node = existing.node + else: + # Construct the new node + constructed_node = f(copy.copy(symbol_node)) + assert self.type is not None # guaranteed by is_class_scope + constructed_node.line = context.line + constructed_node.column = context.column + constructed_node.info = self.type + constructed_node._fullname = self.qualified_name(name) + symbol_node = constructed_node symbol = SymbolTableNode(node.kind, symbol_node, module_public=module_public, From 010c93645ec428b9a4778bfe661d9240a97e7b64 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 19:22:22 -0800 Subject: [PATCH 29/31] flake8 --- mypy/semanal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index b3bf89733546..0d54ee3e5be2 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4814,8 +4814,8 @@ def add_imported_symbol(self, f = cast(Any, lambda x: x) if isinstance(f(symbol_node), (FuncBase, Var)): assert symbol_node is not None - # For imports in class scope, we construct a new node to represent the symbol and set - # its `info` attribute to `self.type`. + # For imports in class scope, we construct a new node to represent the symbol and + # set its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) if ( # The redefinition checks in `add_symbol_table_node` don't work for our From 18286ebd43894606f30ebf4ecd6cc9503e5f7547 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 19:48:39 -0800 Subject: [PATCH 30/31] remove an assert --- mypy/semanal.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 0d54ee3e5be2..8a25b70447ec 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -4809,11 +4809,10 @@ def add_imported_symbol(self, if self.is_class_scope(): # I promise this type checks; I'm just making mypyc issues go away. # mypyc is absolutely convinced that `symbol_node` narrows to a Var in the following, - # when it can also be a FuncBase. Once fixed, casts in the following can be removed. + # when it can also be a FuncBase. Once fixed, `f` in the following can be removed. # See also https://github.com/mypyc/mypyc/issues/892 f = cast(Any, lambda x: x) if isinstance(f(symbol_node), (FuncBase, Var)): - assert symbol_node is not None # For imports in class scope, we construct a new node to represent the symbol and # set its `info` attribute to `self.type`. existing = self.current_symbol_table().get(name) @@ -4827,7 +4826,7 @@ def add_imported_symbol(self, symbol_node = existing.node else: # Construct the new node - constructed_node = f(copy.copy(symbol_node)) + constructed_node = copy.copy(f(symbol_node)) assert self.type is not None # guaranteed by is_class_scope constructed_node.line = context.line constructed_node.column = context.column From c43756bd2a2c2cfadedb3d62a4b6ad8c5118b50e Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Tue, 15 Feb 2022 23:27:51 -0800 Subject: [PATCH 31/31] add test case suggestion from sobolevn --- test-data/unit/check-classes.test | 1 + 1 file changed, 1 insertion(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 2748eb87c6b2..8f3a2c308786 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7158,6 +7158,7 @@ foo: int class Foo: import mod +reveal_type(Foo.mod) # N: Revealed type is "builtins.object" reveal_type(Foo.mod.foo) # N: Revealed type is "builtins.int" [file mod.py] foo: int