Skip to content

Commit 4a7cc03

Browse files
committed
fix callback protocols
1 parent da85a00 commit 4a7cc03

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

crates/red_knot_python_semantic/resources/mdtest/protocols.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,25 +1403,34 @@ static_assert(not is_fully_static(NoParameterAnnotation)) # error: [static-asse
14031403
static_assert(not is_fully_static(NoReturnAnnotation)) # error: [static-assert-error]
14041404
```
14051405

1406-
## `typing.SupportsIndex` and `typing.Sized`
1406+
## Callable protocols
14071407

1408-
`typing.SupportsIndex` is already somewhat supported through some special-casing in red-knot.
1408+
An instance of a protocol type is callable if the protocol defines a `__call__` method:
14091409

14101410
```py
1411-
from typing import SupportsIndex, Literal
1411+
from typing import Protocol
14121412

1413-
def _(some_int: int, some_literal_int: Literal[1], some_indexable: SupportsIndex):
1414-
a: SupportsIndex = some_int
1415-
b: SupportsIndex = some_literal_int
1416-
c: SupportsIndex = some_indexable
1413+
class CallMeMaybe(Protocol):
1414+
def __call__(self, x: int) -> str: ...
1415+
1416+
def _(obj: CallMeMaybe):
1417+
reveal_type(obj(42)) # revealed: str
1418+
obj("bar") # error: [invalid-argument-type]
14171419
```
14181420

1419-
The same goes for `typing.Sized`:
1421+
## Integration test: `typing.SupportsIndex` and `typing.Sized`
1422+
1423+
`typing.SupportsIndex` and `typing.Sized` are two protocols that are very commonly used in the wild.
14201424

14211425
```py
1422-
from typing import Sized
1426+
from typing import SupportsIndex, Sized, Literal
1427+
1428+
def one(some_int: int, some_literal_int: Literal[1], some_indexable: SupportsIndex):
1429+
a: SupportsIndex = some_int
1430+
b: SupportsIndex = some_literal_int
1431+
c: SupportsIndex = some_indexable
14231432

1424-
def _(some_list: list, some_tuple: tuple[int, str], some_sized: Sized):
1433+
def two(some_list: list, some_tuple: tuple[int, str], some_sized: Sized):
14251434
a: Sized = some_list
14261435
b: Sized = some_tuple
14271436
c: Sized = some_sized

crates/red_knot_python_semantic/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4060,7 +4060,7 @@ impl<'db> Type<'db> {
40604060
SubclassOfInner::Class(class) => Type::from(class).signatures(db),
40614061
},
40624062

4063-
Type::NominalInstance(_) => {
4063+
Type::NominalInstance(_) | Type::ProtocolInstance(_) => {
40644064
// Note that for objects that have a (possibly not callable!) `__call__` attribute,
40654065
// we will get the signature of the `__call__` attribute, but will pass in the type
40664066
// of the original object as the "callable type". That ensures that we get errors

0 commit comments

Comments
 (0)