Skip to content

Commit 9c0a6f9

Browse files
authored
Fix crash on self-type in callable protocol (#17499)
Fixes #16629 This is really ad-hoc, but a proper fix would be much more hard, and this currently we have a crash in a relatively common scenario.
1 parent 1acdfd0 commit 9c0a6f9

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

mypy/solve.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@ def pre_validate_solutions(
553553
"""
554554
new_solutions: list[Type | None] = []
555555
for t, s in zip(original_vars, solutions):
556+
if is_callable_protocol(t.upper_bound):
557+
# This is really ad-hoc, but a proper fix would be much more complex,
558+
# and otherwise this may cause crash in a relatively common scenario.
559+
new_solutions.append(s)
560+
continue
556561
if s is not None and not is_subtype(s, t.upper_bound):
557562
bound_satisfies_all = True
558563
for c in constraints:
@@ -567,3 +572,10 @@ def pre_validate_solutions(
567572
continue
568573
new_solutions.append(s)
569574
return new_solutions
575+
576+
577+
def is_callable_protocol(t: Type) -> bool:
578+
proper_t = get_proper_type(t)
579+
if isinstance(proper_t, Instance) and proper_t.type.is_protocol:
580+
return "__call__" in proper_t.type.protocol_members
581+
return False

test-data/unit/check-selftype.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,3 +2132,31 @@ class D:
21322132
x: int
21332133
x: Union[C, D]
21342134
reveal_type(x.x) # N: Revealed type is "Union[__main__.C, builtins.int]"
2135+
2136+
[case testCallableProtocolTypingSelf]
2137+
from typing import Protocol, Self
2138+
2139+
class MyProtocol(Protocol):
2140+
__name__: str
2141+
2142+
def __call__(
2143+
self: Self,
2144+
) -> None: ...
2145+
2146+
def test() -> None: ...
2147+
value: MyProtocol = test
2148+
2149+
[case testCallableProtocolOldSelf]
2150+
from typing import Protocol, TypeVar
2151+
2152+
Self = TypeVar("Self", bound="MyProtocol")
2153+
2154+
class MyProtocol(Protocol):
2155+
__name__: str
2156+
2157+
def __call__(
2158+
self: Self,
2159+
) -> None: ...
2160+
2161+
def test() -> None: ...
2162+
value: MyProtocol = test

0 commit comments

Comments
 (0)