Skip to content

Commit

Permalink
Fix crash on self-type in callable protocol (#17499)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ilevkivskyi committed Jul 6, 2024
1 parent 1acdfd0 commit 9c0a6f9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
12 changes: 12 additions & 0 deletions mypy/solve.py
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@ def pre_validate_solutions(
"""
new_solutions: list[Type | None] = []
for t, s in zip(original_vars, solutions):
if is_callable_protocol(t.upper_bound):
# This is really ad-hoc, but a proper fix would be much more complex,
# and otherwise this may cause crash in a relatively common scenario.
new_solutions.append(s)
continue
if s is not None and not is_subtype(s, t.upper_bound):
bound_satisfies_all = True
for c in constraints:
Expand All @@ -567,3 +572,10 @@ def pre_validate_solutions(
continue
new_solutions.append(s)
return new_solutions


def is_callable_protocol(t: Type) -> bool:
proper_t = get_proper_type(t)
if isinstance(proper_t, Instance) and proper_t.type.is_protocol:
return "__call__" in proper_t.type.protocol_members
return False
28 changes: 28 additions & 0 deletions test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -2132,3 +2132,31 @@ class D:
x: int
x: Union[C, D]
reveal_type(x.x) # N: Revealed type is "Union[__main__.C, builtins.int]"

[case testCallableProtocolTypingSelf]
from typing import Protocol, Self

class MyProtocol(Protocol):
__name__: str

def __call__(
self: Self,
) -> None: ...

def test() -> None: ...
value: MyProtocol = test

[case testCallableProtocolOldSelf]
from typing import Protocol, TypeVar

Self = TypeVar("Self", bound="MyProtocol")

class MyProtocol(Protocol):
__name__: str

def __call__(
self: Self,
) -> None: ...

def test() -> None: ...
value: MyProtocol = test

0 comments on commit 9c0a6f9

Please sign in to comment.