Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,9 @@ def f(self) -> A: ...
if IS_CLASS_OR_STATIC in superflags and IS_CLASS_OR_STATIC not in subflags:
return False

if skip:
# The result is only valid for the partial check, don't pollute the subtype cache.
return True
if not proper_subtype:
# Nominal check currently ignores arg names, but __call__ is special for protocols
ignore_names = right.type.protocol_members != ["__call__"]
Expand Down
22 changes: 22 additions & 0 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
Expand Up @@ -4819,3 +4819,25 @@ class Bad(Generic[T]):
bad: Bad[str] = Bad()
fail: SupportsFoo = bad # E: Incompatible types in assignment (expression has type "Bad[str]", variable has type "SupportsFoo")
[builtins fixtures/tuple.pyi]

[case testCallbackProtocolUnionInferenceOrderIndependent]
from typing import Protocol, TypeVar

T = TypeVar("T")
PT = TypeVar("PT", contravariant=True)

class OneArg(Protocol[PT]):
def __call__(self, x: PT, /) -> None: ...

class TwoArgs(Protocol[PT]):
def __call__(self, x: PT, y: int, /) -> None: ...

def first_arg(fn: OneArg[T] | TwoArgs[T]) -> T: ...

def one(x: int) -> None: ...
def two(x: str, y: int) -> None: ...

reveal_type(first_arg(one)) # N: Revealed type is "builtins.int"
reveal_type(first_arg(two)) # N: Revealed type is "builtins.str"
reveal_type(first_arg(one)) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]
Loading