Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 1 addition & 4 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,6 @@ def f(self) -> A: ...
for member in right.type.protocol_members:
if member in members_not_to_check:
continue
ignore_names = member != "__call__" # __call__ can be passed kwargs
# The third argument below indicates to what self type is bound.
# We always bind self to the subtype. (Similarly to nominal types).
supertype = find_member(member, right, left)
Expand All @@ -1234,9 +1233,7 @@ def f(self) -> A: ...
# Nominal check currently ignores arg names
# NOTE: If we ever change this, be sure to also change the call to
# SubtypeVisitor.build_subtype_kind(...) down below.
is_compat = is_subtype(
subtype, supertype, ignore_pos_arg_names=ignore_names, options=options
)
is_compat = is_subtype(subtype, supertype, options=options)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will need to also remove it from SubtypeContext() ~50 lines below.

else:
is_compat = is_proper_subtype(subtype, supertype)
if not is_compat:
Expand Down
65 changes: 47 additions & 18 deletions test-data/unit/check-protocols.test
Original file line number Diff line number Diff line change
Expand Up @@ -3391,7 +3391,7 @@ test(D) # OK
from typing import Any, Protocol

class P(Protocol):
def foo(self, obj: Any) -> int: ...
def foo(self, obj: Any, /) -> int: ...

class B:
def foo(self) -> int: ...
Expand All @@ -3403,15 +3403,15 @@ test(B) # OK
test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def foo(obj: Any) -> int \
# N: def foo(Any, /) -> int \
# N: Got: \
# N: def foo(self: C) -> str

[case testProtocolClassObjectInstanceMethodArg]
from typing import Any, Protocol

class P(Protocol):
def foo(self, obj: B) -> int: ...
def foo(self, obj: B, /) -> int: ...

class B:
def foo(self) -> int: ...
Expand All @@ -3423,7 +3423,7 @@ test(B) # OK
test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def foo(obj: B) -> int \
# N: def foo(B, /) -> int \
# N: Got: \
# N: def foo(self: C) -> int

Expand All @@ -3432,9 +3432,9 @@ from typing import Any, Protocol, overload

class P(Protocol):
@overload
def foo(self, obj: Any, arg: int) -> int: ...
def foo(self, obj: Any, /, arg: int) -> int: ...
@overload
def foo(self, obj: Any, arg: str) -> str: ...
def foo(self, obj: Any, /, arg: str) -> str: ...

class B:
@overload
Expand All @@ -3458,9 +3458,9 @@ test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P"
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: @overload \
# N: def foo(obj: Any, arg: int) -> int \
# N: def foo(Any, /, arg: int) -> int \
# N: @overload \
# N: def foo(obj: Any, arg: str) -> str \
# N: def foo(Any, /, arg: str) -> str \
# N: Got: \
# N: @overload \
# N: def foo(self: C, arg: int) -> int \
Expand Down Expand Up @@ -3517,7 +3517,7 @@ test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P"
from typing import Any, Protocol, Generic, List, TypeVar

class P(Protocol):
def foo(self, obj: Any) -> List[int]: ...
def foo(self, obj: Any, /) -> List[int]: ...

T = TypeVar("T")
class A(Generic[T]):
Expand All @@ -3532,7 +3532,7 @@ test(B) # OK
test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def foo(obj: Any) -> list[int] \
# N: def foo(Any, /) -> list[int] \
# N: Got: \
# N: def foo(self: A[list[str]]) -> list[str]
[builtins fixtures/list.pyi]
Expand Down Expand Up @@ -3567,7 +3567,7 @@ from typing import Protocol, TypeVar, Union

T = TypeVar("T")
class P(Protocol):
def foo(self, arg: T) -> T: ...
def foo(self, arg: T, /) -> T: ...

class B:
def foo(self: T) -> T: ...
Expand All @@ -3579,7 +3579,7 @@ test(B) # OK
test(C) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def [T] foo(arg: T) -> T \
# N: def [T] foo(T, /) -> T \
# N: Got: \
# N: def [T] foo(self: T) -> T | int

Expand Down Expand Up @@ -3711,7 +3711,7 @@ test(d) # E: Argument 1 to "test" has incompatible type "type[D]"; expected "P"
from typing import Any, Protocol, Type

class P(Protocol):
def foo(self, cls: Any) -> int: ...
def foo(self, cls: Any, /) -> int: ...

class B:
def foo(self) -> int: ...
Expand All @@ -3725,7 +3725,7 @@ test(b) # OK
test(c) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def foo(cls: Any) -> int \
# N: def foo(Any, /) -> int \
# N: Got: \
# N: def foo(self: C) -> str

Expand Down Expand Up @@ -3759,7 +3759,7 @@ from typing import Protocol, Type, TypeVar, Union

T = TypeVar("T")
class P(Protocol):
def foo(self, arg: T) -> T: ...
def foo(self, arg: T, /) -> T: ...

class B:
def foo(self: T) -> T: ...
Expand All @@ -3773,7 +3773,7 @@ test(b) # OK
test(c) # E: Argument 1 to "test" has incompatible type "type[C]"; expected "P" \
# N: Following member(s) of "C" have conflicts: \
# N: Expected: \
# N: def [T] foo(arg: T) -> T \
# N: def [T] foo(T, /) -> T \
# N: Got: \
# N: def [T] foo(self: T) -> T | int

Expand All @@ -3782,7 +3782,7 @@ from typing import Any, Protocol, TypeVar

T = TypeVar("T", contravariant=True)
class P(Protocol[T]):
def foo(self, obj: T) -> int: ...
def foo(self, obj: T, /) -> int: ...

class B:
def foo(self) -> int: ...
Expand All @@ -3804,7 +3804,8 @@ class B:
S = TypeVar("S")
def test(arg: P[S]) -> S: ...
b: Type[B]
reveal_type(test(b)) # N: Revealed type is "__main__.B"
reveal_type(test(b)) # N: Revealed type is "__main__.B" \
# E: Argument 1 to "test" has incompatible type "type[B]"; expected "P[B]"

[case testTypeAliasInProtocolBody]
from typing import Protocol, List
Expand Down Expand Up @@ -4746,3 +4747,31 @@ tmp/a.py:8: note: Expected:
tmp/a.py:8: note: def f(self) -> PNested
tmp/a.py:8: note: Got:
tmp/a.py:8: note: def f(self) -> CNested

[case testProtocolArgNames]
from typing import Protocol

class P1(Protocol):
def foo(self, a: int) -> None: ...

class C1:
def foo(self, b: int) -> None: pass

x1: P1 = C1() # E: Incompatible types in assignment (expression has type "C1", variable has type "P1")

class P2(Protocol):
def foo(self, a: int) -> None: ...

class C2:
def foo(self, *args: int) -> None: pass

x2: P2 = C2() # E: Incompatible types in assignment (expression has type "C2", variable has type "P2")

class P3(Protocol):
def foo(self, a: int, /) -> None: ...

class C3:
def foo(self, *args: int) -> None: pass

okay3: P3 = C3()
[builtins fixtures/tuple.pyi]
Loading