I started to implement parts of the draft PEP 646 within pyright this evening. I figured this exercise might be helpful in informing our discussion and teasing out additional questions and issues. Here's what I've uncovered so far.
*Grammar Changes* The grammar will need to change to support star expressions (i.e. unpack operator) within type annotations and in subscripts. If unpack operators are permitted within a subscript, how will that be handled at runtime? For example, in the expression `x[A, *B]`, what value will be passed to the `__getitem__` method for instance `x`? Will the runtime effectively replace `*B` with `typing.Unpack[B]`?
Will star expressions be allowed in slice expressions? I presume no.
*Zero-length Variadics* It's legal to pass no arguments to a `*args` parameter. For example: ```python def foo(*args: Any): ... foo() # This is fine ```
*Unknown-length Variadics* Am I correct in assuming that it's not OK to pass zero arguments to a `*args` parameter that has a variadic TypeVar annotation? ```python def foo(*args: *T): ... foo() I presume this is an error? ```
Also, it's generally OK to pass an arbitrary-length list of arguments to an `*args` parameter using an unpack operator. ```python def foo(*args: Any): ... def bar(x: Tuple[int, ...]): foo(*x) # This is allowed ``` I presume that it should be an error pass an arbitrary-length list of arguments to an `*args` parameter if it has a variadic TypeVar annotation? ```python def foo(*args: *T): ... def bar(x: Tuple[int, ...], y: Iterable[int], z: Tuple[int]): foo(*x) # I presume this is an error? foo(*y) # I presume this is an error? foo(*z) # This is allowed ``` If my assumption is correct that this should be flagged as an error by a type checker, will it also be a runtime error? I'm guessing the answer is no, there's no way to distinguish such an error at runtime. If my assumption is incorrect and this permitted, does the variadic type variable effectively become "open-ended" (i.e. the dimensionality of the variadic becomes unknown)? If so, how does it work with concatenation? I think it's better to make this an error.
* Other Observations * This won't be an easy PEP to implement in type checkers, even with the simplifications I've recommended. It's going to be a heavy lift, which means it's going to be a long time before all type checkers support it. Compared to other recent type-related PEPs like 604, 612, 613, and 647, this PEP will require significantly more work to implement and get everything right. That could significantly delay the time before it can be used in typeshed and other public stubs. This bolsters my conviction that we should embrace simplifications where possible.
After this exercise, I'm even more convinced that we should support only unpacked usage ("*T") and not support packed ("T") for variadic type variables — and that we should use the existing TypeVar rather than introducing TypeVarTuple. In the rare cases where a packed version is desired, it can be expressed as `Tuple[*T]`. For example:
```python T = TypeVar("T") def func(*args: *T) -> Tuple[*T]: ... ```
By requiring `*T` everywhere for a variadic type variable, we will reduce confusion for users and simplify the spec and implementation.
-- Eric Traut Contributor to pyright and pylance Microsoft Corp.