Wow, Eric, that was fast! Thanks for your great work! :)

**PEP draft**: I've updated the current draft of the PEP at to reflect the decisions we've made. I think it now more or less reflects the behaviour in Pyright's implementation (minus aliases, which I've yet to rewrite the PEP section for).

One small thing that's different to our discussion is the behaviour of a `Union` of an empty `TypeVarTuple`: I realised that assigning a type of `NoReturn` to such `Union`s would only make sense if the `Union` in question was in a return annotation, so I've stuck with saying that the type-checker should produce an error so that the behaviour is consistent between `Union` in returns and `Union` elsewhere.

**Reply to Guido**

> No, that's not how type variables work at all!

Ahh, thanks for clarifying. This was pretty eye-opening. I've tried to make the expected behaviour for `TypeVarTuple` explicit in the current draft of the PEP by saying that we disallow `Tuple[Union[A, B]]`, and that types must match exactly. (I haven't mentioned the 'class hierarchies' case in the draft because we've defined `TypeVarTuple` as invariant for the time being.)

On Sun, 31 Jan 2021 at 01:30, Eric Traut <> wrote:
I've done a first-cut implementation of PEP 646 in pyright 1.1.107. I just published this version, so you can try it by installing the Pyright extension in VS Code.

Specific notes about my current implementation:
* It supports `TypeVarTuple`, which is exported by the typing_extensions.pyi that ships with pyright.
* It supports `Unpack`, also exported by typing_extensions.pyi.
* It does not currently support `*` syntax, since that will be introduced with PEP 637 functionality.
* It does not allow packed usage of a TypeVarTuple. All uses of a TypeVarTuple must be contained with an `Unpack`, and errors are generated if they are not.
* If a TypeVarTuple appears within a subscript for a type annotation, it must be the last entry (i.e. no suffixes). The one exception is `Union`, which allows it to appear anywhere. I figured this was justified because the order of type arguments within a `Union` are not relevant.
* If a TypeVarTuple appears within a class declaration, only one is allowed, and it must be after all other type variables. The order can be forced by including an explicit `Generic` that defines the type parameter ordering.
* At most one TypeVarTuple can appear within a subscript when specializing a class (e.g. `Tuple[Ts1, Ts2]` is an error). The one exception is `Union`, which allows for multiple TypeVarTuples to appear. This creates an ambiguity for the constraint solver, but this ambiguity already exists for traditional TypeVars.
* Type aliases may contain at most one TypeVarTuple, and it must be after all other TypeVars that parameterize the type alias (e.g. `Alias1 = Union[List[T], Tuple[Unpack[Ts]]]` is allowed, but `Alias2 = Union[Tuple[Unpack[Ts]], List[T]]` is an error. Unlike with class declarations, there's no way to force the ordering of type parameters within a type alias, which is somewhat constraining.
* An attempt to assign an open-ended tuple to a TypeVarTuple during constrain solving results in an error.
* A Callable may include a TypeVarTuple within its parameter type list, but only one is allowed, and it must be in the last entry. Other cases are flags as errors.
* If a TypeVarTuple appears more than once in a function signature, the tuples that are assigned to it must match in both length and in type. There is no attempt to widen the type to accommodate differences.

As I anticipated, this was a very large and complex feature to implement. If you're curious, here's the [commit](

I've implemented a bunch of test cases. Perhaps these will be of use for other type checker maintainers as when they add support for this PEP. The test samples can be found [here]( (There are 8 test files and many dozens of test cases for this feature currently.)

Feedback and bug reports are welcome.

Eric Traut
Contributor to Pyright and Pylance
Microsoft Corp.
Typing-sig mailing list --
To unsubscribe send an email to
Member address: