One thing that jumps out to me from reading the mypy issue is that for a while there was no way at all to express a Callable ...
in a def
statement, first because it was inexpressible, then because mypy’s support for ParamSpec
was incomplete.
Now it sounds like the following works? (Copying from Subtyping rules for `...` in callable types)
class Concrete:
def __call__(self, x: int, *, y: int) -> None:
pass
class Proto5[**P](Protocol):
def __call__(self, x: int, *args: P.args, **kwargs: P.kwargs) -> None: ...
f: Proto5[...] = Concrete() # OK (mypy and pyright)
I wonder if we could get rid of the special case and suggest using ParamSpec
instead.
I don’t love the (*args: ..., **kwargs: ...)
idea because I think it’s rather non-obvious what ...
means in this context. In this issue, there’s some support for making a ...
parameter annotation mean “inferred type.” I’m not advocating for this, just using it as an example of an also-plausible and entirely different interpretation.