TypeVarTuple and typing.py
Pradeep Kumar Srinivasan
11th January 2021
What we'd need to do
What we're aiming for
Generic should be able to accept
Tensor should be able to accept arbitrary parameters:
Syntax change: *Ts
Arity check
GenericMeta is a metaclass that checks that generic classes are provided the right number and types of arguments
Tensor will need to accept an arbitrary number of arguments
(where L = Literal)
__parameters__
# * __parameters__ is a tuple of unique free type parameters of a generic
# type, for example, Dict[T, T].__parameters__ == (T,)
Consider:
Ts = TypeVarTuple('Ts')
class Foo(Generic[*Ts]): ...
foo: Foo[int, str] = Foo()
class Bar(Generic[Ts]): ...
bar: Bar[Tuple[int, str]] = Bar()
We need to distinguish Ts and *Ts / Unpack[Ts]
Should TypeVarTuple subclass TypeVar?
Pro subclassing:
Con subclassing:
Unpack[Ts]
What if Tensor is given no parameters?
Tensors of arbitrary rank
def complicated_function(t: Tensor[Any, …]) -> int: …
my_tensor: Tensor[L[480], L[360]]
complicated_function(my_tensor)
Other things
Anything else?
class _TypeAlias(_TypingBase, _root=True):
"""Internal helper class for defining generic variants of concrete types."""
Thank you!
Extra slides
Unexpanded Ts
# * __parameters__ is a tuple of unique free type parameters of a generic�# type, for example, Dict[T, T].__parameters__ == (T,)
Therefore, for generics like Foo(Generic[T1, *Ts, T2, Ts2]), Ts (a TypeVarTuple) would also need to appear in __parameters__.
The main wrinkle is that callers currently expect Generic[...].__parameters__ to be TypeVars. There are quite a few isinstance(foo, TypeVar) in typing.py and typing_extensions.py (and in other typing-related packages, such as MonkeyType).
We would probably have to make an TypeVarTuple a subclass of TypeVar. That should be fine.
__parameters__
But what about class Foo(Generic[T1, Unpack[Ts], T2, Ts2])?
This is trickier. We'd have to change the invariant for __parameters__ to have a mixture of TypeVars and Unpack. This would be a breaking change for third-party packages that expect __parameters__ to be TypeVars.
Also, Unpack can take a partially or fully concrete parameter, like Tuple[int, Unpack[Ts]].
3. We'd also need to change a substitution function in typing.py that is used for instantiating a generic alias.
4. I'd be curious to find out if there are any other expected behaviors from Generic or TypeVar.