Skip to content

Commit 380e2ba

Browse files
committed
Bind selftypes in decorated classmethods
1 parent d68ea35 commit 380e2ba

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

mypy/checkmember.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,9 +1203,13 @@ def analyze_class_attribute_access(
12031203
t = get_proper_type(t)
12041204
if isinstance(t, FunctionLike) and is_classmethod:
12051205
t = check_self_arg(t, mx.self_type, False, mx.context, name, mx.msg)
1206-
result = add_class_tvars(
1206+
t = add_class_tvars(
12071207
t, isuper, is_classmethod, is_staticmethod, mx.self_type, original_vars=original_vars
12081208
)
1209+
if is_decorated and not is_staticmethod:
1210+
t = expand_self_type_if_needed(t, mx, node.node.var, itype, is_class=is_classmethod)
1211+
1212+
result = t
12091213
# __set__ is not called on class objects.
12101214
if not mx.is_lvalue:
12111215
result = analyze_descriptor_access(result, mx)

test-data/unit/check-selftype.test

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,3 +2221,44 @@ class B:
22212221
class C(A, B): # OK: both methods take Self
22222222
pass
22232223
[builtins fixtures/tuple.pyi]
2224+
2225+
[case testSelfInFuncDecoratedClassmethod]
2226+
from collections.abc import Callable
2227+
from typing import Self, TypeVar
2228+
2229+
T = TypeVar("T")
2230+
2231+
def debug(make: Callable[[type[T]], T]) -> Callable[[type[T]], T]:
2232+
return make
2233+
2234+
class Foo:
2235+
@classmethod
2236+
@debug
2237+
def make(cls) -> Self:
2238+
return cls()
2239+
2240+
class Bar(Foo): ...
2241+
2242+
reveal_type(Foo.make()) # N: Revealed type is "__main__.Foo"
2243+
reveal_type(Foo().make()) # N: Revealed type is "__main__.Foo"
2244+
reveal_type(Bar.make()) # N: Revealed type is "__main__.Bar"
2245+
reveal_type(Bar().make()) # N: Revealed type is "__main__.Bar"
2246+
[builtins fixtures/tuple.pyi]
2247+
2248+
[case testSelfInClassDecoratedClassmethod]
2249+
from typing import Callable, Generic, TypeVar, Self
2250+
2251+
T = TypeVar("T")
2252+
2253+
class W(Generic[T]):
2254+
def __init__(self, fn: Callable[..., T]) -> None: ...
2255+
def __call__(self) -> T: ...
2256+
2257+
class Check:
2258+
@W
2259+
def foo(self) -> Self:
2260+
...
2261+
2262+
reveal_type(Check.foo()) # N: Revealed type is "def () -> __main__.Check"
2263+
reveal_type(Check().foo()) # N: Revealed type is "__main__.Check"
2264+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)