You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
subscripting a class with a TypeVarTuple followed by a defaulted ParamSpec reports "Can only replace ParamSpec" and infers Any #22375
PEP 696 and the typing spec (section "Defaults following TypeVarTuple") allow a ParamSpec with a default after a TypeVarTuple. The spec's example also gives the TypeVarTuple a default; the result below is the same with and without it. mypy accepts the class definition, but subscripting it gives an error: the last type argument is taken as the argument for the ParamSpec, and the result is Foo[*tuple[Any, ...], Any].
The old-style spelling (Ts = TypeVarTuple("Ts"), P = ParamSpec("P", default=[float, bool]), class Foo(Generic[Unpack[Ts], P]), a parameter annotated Foo[int, str]) gives the same message on the subscript.
Actual Behavior
t.py:13: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "str" [misc]
t.py:14: error: Expression is of type "tuple[Any, ...]", not "tuple[int, str]" [assert-type]
t.py:15: error: Expression is of type "def (*Any, **Any) -> None", not "Callable[[float, bool], None]" [assert-type]
t.py:17: error: Can only replace ParamSpec with a parameter types list or another ParamSpec, got "str" [misc]
t.py:18: error: Expression is of type "tuple[Any, ...]", not "tuple[int, str]" [assert-type]
t.py:19: error: Expression is of type "def (*Any, **Any) -> None", not "Callable[[bytes], None]" [assert-type]
With a default on the TypeVarTuple too (class Foo[*Ts = *tuple[int, str], **P = [float, bool]], the example from the spec) the result is the same. This is also what the typing conformance suite shows for mypy on generics_defaults.py, lines 203 to 205.
Expected Behavior
No errors. Foo[int, str] is Ts = (int, str), P = [float, bool] and Foo[int, str, [bytes]] is Ts = (int, str), P = [bytes], as in the spec. A ParamSpec argument has to be a list, ... or another ParamSpec, so str cannot be one and there is no ambiguity with the TypeVarTuple. pyright 1.1.414 and ty 0.0.97 accept the program.
Note: CPython 3.13.16, 3.14.8 and 3.15.0 raise TypeError: Type parameter with a default follows TypeVarTuple when this class is created (python/typing#2211, a runtime bug), so the snippet is for type checking only.
My Environment
Mypy version used: 2.4.0, 2.4.1 and master 2.5.0+dev.879da562
Activity
Fix TypeVarTuple with defaulted ParamSpec