Skip to content

Commit 975fbe5

Browse files
committed
Fix difference between callables and callback protocols
Fixes #15926 (comment)
1 parent 5783af4 commit 975fbe5

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

mypy/checkmember.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -779,12 +779,12 @@ def analyze_var(
779779

780780
call_type: Optional[ProperType] = None
781781
if var.is_initialized_in_class and (not is_instance_var(var) or mx.is_operator):
782-
if isinstance(typ, FunctionLike) and not typ.is_type_obj():
783-
call_type = typ
784-
elif var.is_property:
782+
if var.is_property and (not isinstance(typ, FunctionLike) or typ.is_type_obj()):
785783
call_type = get_proper_type(_analyze_member_access("__call__", typ, mx))
786784
else:
787785
call_type = typ
786+
if isinstance(call_type, Instance) and call_type.type.get_method("__call__"):
787+
call_type = get_proper_type(_analyze_member_access("__call__", typ, mx))
788788

789789
if isinstance(call_type, FunctionLike) and not call_type.is_type_obj():
790790
if mx.is_lvalue:

test-data/unit/check-protocols.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4127,3 +4127,30 @@ class P(Protocol):
41274127

41284128
class C(P): ...
41294129
C(0) # OK
4130+
4131+
4132+
[case testCallbackProtocolMethod]
4133+
from typing import Callable, Protocol
4134+
4135+
class CallbackProtocol(Protocol):
4136+
def __call__(self, __x: int) -> int: ...
4137+
4138+
def make_method_protocol() -> CallbackProtocol: ...
4139+
def make_method_callable() -> Callable[[int], int]: ...
4140+
4141+
class ClsProto:
4142+
meth = make_method_protocol()
4143+
4144+
class ClsCall:
4145+
meth = make_method_callable()
4146+
4147+
reveal_type(ClsProto.meth) # N: Revealed type is "__main__.CallbackProtocol"
4148+
reveal_type(ClsCall.meth) # N: Revealed type is "def (builtins.int) -> builtins.int"
4149+
4150+
def takes(p: ClsProto, c: ClsCall) -> None:
4151+
reveal_type(p.meth(0)) # E: Invalid self argument "ClsProto" to attribute function "meth" with type "Callable[[int], int]" \
4152+
# E: Too many arguments for "__call__" of "CallbackProtocol" \
4153+
# N: Revealed type is "builtins.int"
4154+
reveal_type(c.meth(0)) # E: Invalid self argument "ClsCall" to attribute function "meth" with type "Callable[[int], int]" \
4155+
# E: Too many arguments \
4156+
# N: Revealed type is "builtins.int"

0 commit comments

Comments
 (0)