-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-43224: Forbid TypeVar substitution with Unpack #32031
bpo-43224: Forbid TypeVar substitution with Unpack #32031
Conversation
for A in G, Tuple: | ||
B = A[T, Unpack[Ts], str, T2] | ||
with self.assertRaises(TypeError): | ||
B[int, Unpack[Ts]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remind me where PEP 646 forbids this? Assuming Unpack[Ts]
=== *Ts
, it seems this is forbidding the following:
class G(Generic[*Ts]): ...
B = G[T, *Ts, str, T2]
X = B[int, *Ts] # <-- TypeError here
What is wrong with X
that isn't wrong with B
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll rewrite it as B[int, *Ts2]
, so we could unambiguously refer to variables.
AFAIK PEP 646 does not cover such case. It does not specify the result.
But what can be the result of substitution B[int, *Ts2]
? T
is substituted with int
, T2
should be substituted with the last item of *Ts2
, and *T
should be substituted with all but the last items of *Ts2
. But we cannot express this, because Ts2
is a variable. If we substitute *Ts2
with an empty sequence of types (X[()]
), there would not be a value for T2
.
I think that it is better to make it an error:
def f(a: tuple[*Ts2]) -> B[int, *Ts2]: ...
You should write
def f(a: tuple[*Ts2, T3]) -> B[int, *Ts2, T3]: ...
to make it having some sense.
There is a workaround of this problem. It may even make the code more clear. You can see, that a
should be a tuple containing at least 1 item. T2
in B
will be substituted with the type of the last item, and *Ts
in B
will be substituted with the rest of types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mrahtz what do you think of this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the prod, Jelle. I agree with Serhiy - looks like this is one of the cases we should forbid at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good in principle, pending resolution of Guido's question.
https://bugs.python.org/issue43224