PEP 646 – Variadic Generics multiple matching variants
Have this example: ``` from __future__ import annotations from typing import Generic from typing import TypeVar from typing import TypeVarTuple Shape = TypeVarTuple("Shape") T = TypeVar("T") T1 = TypeVar("T1") class Array(Generic[*Shape]): ... y: Array[int, *tuple[float, ...], int, str] = Array() def expect_variadic_array(x: Array[int, T, *Shape, T1]) -> Array[*Shape, T, T1]: ... expr = expect_variadic_array(y) which type is expected for expr? ``` Here we can assign: ``` int -> int T -> int (*float empty) *Shape -> empty T1 -> str so return Array[int, str] ``` or ``` int -> int T -> float *Shape -> int T1 -> str ``` so T can be either int or float and *Shape can be either () or (int, float*)
I think it's indeterminate and undefined. I recommend against relying on something like this. Different type checkers will inevitably produce different answers here. Similar ambiguities arise for unpacking and assigning arguments to parameters when indeterminate-length tuples are involved. ``` def func(y: tuple[int, *tuple[float, ...], int, str]): a, b, *c, d = y ``` -Eric -- Eric Traut Contributor to Pyright & Pylance Microsoft
Apologies for the slow reply - I'm only just now finally catching up after
vacation.
If we're substituting:
int, *tuple[float, ...], int, str
Into:
int, T, *Shape, T1
Then I believe what should actually happen is:
T = float
T1 = str
Shape = tuple[*tuple[float, ...], int]
The reasoning is that, for arbitrary-length tuples like tuple[float, ...],
we assume it always has enough items to fill all the type variables. We
chose this behaviour in order to be consistent with existing behaviour for
arbitrary-length tuples:
t: tuple[int, ...]
a, b = t # Valid
a, b, c = t # Also valid
def bar(a: int, *b: int): ...
bar(*t) # Valid
Note that this last example is somewhat surprising - `bar` supposedly has
to take at least one argument, but the arbitrary-length tuple we're passing
in could have zero elements. But *shrug* this is the way it is.
This is admittedly rather under-documented. We're trying to amend PEP 646
in https://github.com/python/peps/pull/2883 with the details of how this
works. If the SC decides against revising an already-accepted PEP, though,
we'll try and find somewhere else to document it.
On Wed, 2 Nov 2022 at 17:03, Eric Traut
I think it's indeterminate and undefined. I recommend against relying on something like this. Different type checkers will inevitably produce different answers here.
Similar ambiguities arise for unpacking and assigning arguments to parameters when indeterminate-length tuples are involved.
``` def func(y: tuple[int, *tuple[float, ...], int, str]): a, b, *c, d = y ```
-Eric
-- Eric Traut Contributor to Pyright & Pylance Microsoft _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: mrahtz@google.com
participants (3)
-
andrey.matveev.mano@gmail.com
-
Eric Traut
-
Matthew Rahtz