diff --git a/mypy/typeops.py b/mypy/typeops.py index 8453da4dd31c..a85560d3f1da 100644 --- a/mypy/typeops.py +++ b/mypy/typeops.py @@ -119,6 +119,11 @@ def tuple_fallback(typ: TupleType) -> Instance: and unpacked_type.type.fullname == "builtins.tuple" ): items.append(unpacked_type.args[0]) + elif isinstance(unpacked_type, TupleType): + # A fixed-length tuple being unpacked (e.g. *tuple[int, str], possibly + # via a type alias) isn't a TypeVarTupleType or a variable-length tuple + # Instance, but its own fallback already gives us the right element type. + items.append(tuple_fallback(unpacked_type).args[0]) else: raise NotImplementedError else: diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 8c37e48d7c33..b6f574efa524 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -2310,3 +2310,21 @@ type Alias[T] = list[T] def g[T = int](x: T) -> T: ... [out] _testNativeParserPEP695InStubNoVersionError.py:3: note: Revealed type is "def [T] (x: T) -> T" + +[case testNoCrashOnFixedTupleUnpackInGenericInferenceContext] +# https://github.com/python/mypy/issues/21933 +# flags: --python-version=3.12 +from collections import deque + +type Inner = tuple[int, str] +type Outer = tuple[bool, *Inner] + + +class K(Base): + q: deque[Outer] = deque() + reveal_type(q) + + +class Base: ... +[out] +_testNoCrashOnFixedTupleUnpackInGenericInferenceContext.py:11: note: Revealed type is "collections.deque[tuple[bool, *tuple[int, str]]]"