Draft of typing spec chapter for tuples

I’ve written a first draft of a new chapter for the typing spec that focuses on type checker behaviors for tuples. There was already some information about tuples scattered throughout the spec, but this is an attempt to consolidate the information in one place and address some ambiguities.

If you are interested in reviewing the draft, you can find it in this PR . Minor feedback (typos, wording suggestions, etc.) can be added directly to the PR. For significant questions or areas of potential disagreement, please post to this thread so community members get better visibility and can engage in the discussion.

This draft incorporates the results of the long discussion about tuple[T, ...].

Thanks, it’s really good to see the consolidation and overhaul of the typing spec!

Maybe it’s worth mentioning that arbitrary-length tuples have exactly two elements – the type and the ellipsis – and any other form is invalid:

tuple[...]  # invalid
tuple[..., int]  # invalid
tuple[int, str, ...]  # invalid
tuple[*tuple[str], int, ...]  # invalid
1 Like

Here’s a question that came up in the PR comments from @superbobry. The current draft wording states:

The tuple class derives from Sequence[T_co] where T_co is a covariant
(non-variadic) type variable. The specialized type of T_co should be computed
by a type checker based on the union of element types within the tuple.

Mypy currently uses a “join” of the element types rather than a union. I think a union is more correct (and precise), but a join is defensible. It means that a bunch of useful type information is discarded, and an overly-wide type is produced. This tends to produce downstream false positive errors.

from typing import Sequence, TypeVar

T = TypeVar("T")

def make_seq(x: Sequence[T]) -> Sequence[T]:
    return x

def func2(x: tuple[str, int]):
    # Pyright reveals: Sequence[int | str]
    # Mypy reveals: Sequence[object]

Question to the community: Should the spec’s language dictate a union here, or should it be more vague and allow any type that is a supertype of all element types?

I think my personal preference definitely is an union. I have found that mypy is too eager to use a join instead of an union in quite a few cases (not just this specific one), so I’d like it if the specification steered type checkers towards a union in more cases, at least in covariant cases, since the union will still be accepted in places that accept the joined type. In invariant cases it’s a tougher call to make, since whichever version you pick, you will end up with false positives.

I’d prefer to keep this out of the spec. We’ve mostly kept type inference rules out of the spec for now, and I think that’s fine, as they usually don’t affect interoperability. I’d prefer to first focus on ironing out areas where there is more consequential disagreement among type checkers.

I buy that. I’ll update the spec to make it clear that type checkers should calculate this value, which must be a supertype of all the element types. This gives individual type checkers the leeway to choose how they implement this.

1 Like

Thanks to everyone who provided feedback and PR reviews. The Typing Council has approved the new chapter on tuples, and it is now officially incorporated into the typing spec.

1 Like