diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 4ac99d3fa8e2..55225b20d4ac 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -710,7 +710,8 @@ def find_node_type(node: Union[Var, FuncBase], itype: Instance, subtype: Type) - and node.is_initialized_in_class and not node.is_staticmethod)): assert isinstance(typ, FunctionLike) - signature = bind_self(typ, subtype) + signature = bind_self(typ, subtype, + is_classmethod=isinstance(node, Var) and node.is_classmethod) if node.is_property: assert isinstance(signature, CallableType) typ = signature.ret_type diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index 7e37276a3f75..b96e9b589ae5 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -802,6 +802,37 @@ class Bad(metaclass=Meta): Good.do_x() Bad.do_x() # E: Invalid self argument "Type[Bad]" to attribute function "do_x" with type "Callable[[Type[T]], T]" +[case testSelfTypeProtocolClassmethodMatch] +from typing import Type, TypeVar, Protocol + +T = TypeVar('T') + +class HasDoX(Protocol): + @classmethod + def do_x(cls: Type[T]) -> T: + ... + +class Good: + @classmethod + def do_x(cls) -> 'Good': + ... + +class Bad: + @classmethod + def do_x(cls) -> Good: + ... + +good: HasDoX = Good() +bad: HasDoX = Bad() +[builtins fixtures/classmethod.pyi] +[out] +main:21: error: Incompatible types in assignment (expression has type "Bad", variable has type "HasDoX") +main:21: note: Following member(s) of "Bad" have conflicts: +main:21: note: Expected: +main:21: note: def do_x(cls) -> Bad +main:21: note: Got: +main:21: note: def do_x(cls) -> Good + [case testSelfTypeNotSelfType] # Friendlier error messages for common mistakes. See #2950 class A: