This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author matthew.rahtz
Recipients AlexWaygood, JelleZijlstra, gvanrossum, kj, matthew.rahtz, mrahtz, serhiy.storchaka
Date 2022-04-04.23:28:09
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1649114889.48.0.521768587246.issue47006@roundup.psfhosted.org>
In-reply-to
Content
Apologies for the slow reply - coming back to this now that the docs and pickling issues are mostly sorted.

[Serhiy]

> > Alias = C[T, *Ts]
> > Alias2 = Alias[*tuple[int, ...]]
> > # Alias2 should be C[int, *tuple[int, ...]]
>
> tuple[int, ...] includes also an empty tuple, and in this case there is no value for T.

This was my initial intuition too, but Pradeep pointed out to me in https://github.com/python/cpython/pull/31021#discussion_r815853784 that for tuple[int, ...], Python has chosen the opposite mindset: instead of assuming the worst-case scenario, we assume the best-case scenario. Thus, the following type-checks correctly with mypy (https://mypy-play.net/?mypy=latest&python=3.10&gist=b9ca66fb7d172f939951a741388836a6):

def return_first(tup: tuple[int, ...]) -> int:
    return tup[0]
tup: tuple[()] = ()
return_first(tup)

> > We actually deliberately chose not to unpack concrete tuple types - see the description of https://github.com/python/cpython/pull/30398, under the heading 'Starred tuple types'. (If you see another way around it, though, let me know.)
> 
> You assumed that *tuple[str, bool] in def foo(*args: *tuple[str, bool]) should give foo.__annotations__['args'] = tuple[str, bool], but it should rather give (str, bool). No confusion with tuple[str, bool].

Fair point, we could *technically* distinguish between tuple[str, bool] and (str, bool). But if I was a naive user and I saw `foo.__annotations__['args'] == (str, bool)`, I don't think it'd be immediately obvious to me that the type of `args` was `*tuple[str, bool]`.

Also though, there's a second reason mentioned in https://github.com/python/cpython/pull/30398 why `(str, bool)` wouldn't be the best choice. We decided that the runtime behaviour of `*args: *something` should be that we essentially do `(*something,)[0]`. If we made `tuple[int, str]` unpack to `(int, str)`, then we'd end up with `__annotations__['args'] == (int,)`.

> And one of PEP 646 options is to implement star-syntax only in subscription, not in var-parameter type annotations.

As in, we would allow `Generic[*Ts]`, but not `*args: *Ts`? That'd be a *major* change to the PEP - not an option I'm willing to consider at this stage in the process.

> > I'm also not sure about this one; disallowing unpacked TypeVarTuples in argument lists to generic aliases completely (if I've understood right?)
>
> No, it will only be disallowed in substitution of a VarType. Tuple[T][*Ts] -- error. Tuple[*Ts][*Ts2] -- ok.

Ah, gotcha. My mistake.

[Guido]

I ran out of time this evening :) Will reply properly soon.
History
Date User Action Args
2022-04-04 23:28:09matthew.rahtzsetrecipients: + matthew.rahtz, gvanrossum, serhiy.storchaka, JelleZijlstra, kj, mrahtz, AlexWaygood
2022-04-04 23:28:09matthew.rahtzsetmessageid: <1649114889.48.0.521768587246.issue47006@roundup.psfhosted.org>
2022-04-04 23:28:09matthew.rahtzlinkissue47006 messages
2022-04-04 23:28:09matthew.rahtzcreate