From debf2a59a08c9d969a2369a70b3b9f787f523e45 Mon Sep 17 00:00:00 2001 From: bxff <51504045+bxff@users.noreply.github.com> Date: Sun, 1 Mar 2026 02:16:28 +0530 Subject: [PATCH] Fix IndexError when unpacking empty tuple in type alias When expanding type arguments for a builtins.tuple instance, the normalization code accessed args[0] without checking if args was non-empty. This caused an IndexError when Unpack[tuple[()]] was used in a type alias, since the empty tuple expansion produces zero args. Fixes #20913 --- mypy/expandtype.py | 2 +- test-data/unit/check-python312.test | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 5790b717172ac..ea0e1e0d9ac48 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -223,7 +223,7 @@ def visit_instance(self, t: Instance) -> Type: # See: https://github.com/python/mypy/issues/16649 return t.copy_modified(args=args) - if t.type.fullname == "builtins.tuple": + if t.type.fullname == "builtins.tuple" and len(args) > 0: # Normalize Tuple[*Tuple[X, ...], ...] -> Tuple[X, ...] arg = args[0] if isinstance(arg, UnpackType): diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 0521722b47c16..986b24c74cf33 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -2237,3 +2237,17 @@ class D[*Ts](Generic[Unpack[Us]]): # E: Generic[...] base class is redundant \ # E: Can only use one type var tuple in a class def pass [builtins fixtures/tuple.pyi] + +[case testUnpackEmptyTupleInTypeAliasNoCrash] +# https://github.com/python/mypy/issues/20913 +from typing import Unpack + +class C[*Ts]: + pass + +type T[T, *Ts] = C[*Ts] + +x: T[bool, Unpack[tuple[()]]] +reveal_type(x) # N: Revealed type is "__main__.C[Unpack[builtins.tuple]]" +[builtins fixtures/tuple.pyi] +[typing fixtures/typing-full.pyi]