Skip to content

Commit 9958295

Browse files
authored
Bind self correctly when mapping class methods from supertype (#7474)
Fixes #2511
1 parent 8e960b3 commit 9958295

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

mypy/checker.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,11 @@ def bind_and_map_method(self, sym: SymbolTableNode, typ: FunctionLike,
15301530
"""
15311531
if (isinstance(sym.node, (FuncDef, OverloadedFuncDef, Decorator))
15321532
and not is_static(sym.node)):
1533-
bound = bind_self(typ, self.scope.active_self_type())
1533+
if isinstance(sym.node, Decorator):
1534+
is_class_method = sym.node.func.is_class
1535+
else:
1536+
is_class_method = sym.node.is_class
1537+
bound = bind_self(typ, self.scope.active_self_type(), is_class_method)
15341538
else:
15351539
bound = typ
15361540
return cast(FunctionLike, map_type_from_supertype(bound, sub_info, super_info))

test-data/unit/check-generics.test

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,3 +2062,52 @@ class A:
20622062
x, y = A()
20632063
reveal_type(x) # N: Revealed type is 'Any'
20642064
reveal_type(y) # N: Revealed type is 'Any'
2065+
2066+
[case testSubclassingGenericSelfClassMethod]
2067+
from typing import TypeVar, Type
2068+
2069+
AT = TypeVar('AT', bound='A')
2070+
2071+
class A:
2072+
@classmethod
2073+
def from_config(cls: Type[AT]) -> AT:
2074+
...
2075+
2076+
class B(A):
2077+
@classmethod
2078+
def from_config(cls: Type[B]) -> B:
2079+
return B()
2080+
[builtins fixtures/classmethod.pyi]
2081+
2082+
[case testSubclassingGenericSelfClassMethodOptional]
2083+
# flags: --strict-optional
2084+
from typing import TypeVar, Type, Optional
2085+
2086+
AT = TypeVar('AT', bound='A')
2087+
2088+
class A:
2089+
@classmethod
2090+
def from_config(cls: Type[AT]) -> Optional[AT]:
2091+
return None
2092+
2093+
class B(A):
2094+
@classmethod
2095+
def from_config(cls: Type[B]) -> Optional[B]:
2096+
return B()
2097+
[builtins fixtures/classmethod.pyi]
2098+
2099+
[case testSubclassingGenericSelfClassMethodNonAnnotated]
2100+
from typing import TypeVar, Type
2101+
2102+
AT = TypeVar('AT', bound='A')
2103+
2104+
class A:
2105+
@classmethod
2106+
def from_config(cls: Type[AT]) -> AT:
2107+
...
2108+
2109+
class B(A):
2110+
@classmethod
2111+
def from_config(cls) -> B:
2112+
return B()
2113+
[builtins fixtures/classmethod.pyi]

0 commit comments

Comments
 (0)