Skip to content

Type substitution in generic aliases does not work if ParamSpec is followed by TypeVarTuple #99379

Closed

Description

@serhiy-storchaka

The following code:

from typing import *
P = ParamSpec('P')
Ts = TypeVarTuple('Ts')
C = Callable[P, Tuple[*Ts]]
C[[int], str, bytes]

gives an error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 363, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1393, in __getitem__
    new_args = self._determine_new_args(args)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1417, in _determine_new_args
    args = prepare(self, args)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1229, in __typing_prepare_subst__
    return _prepare_paramspec_params(alias, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 297, in _prepare_paramspec_params
    _check_generic(cls, params, len(cls.__parameters__))
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 274, in _check_generic
    raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"
TypeError: Too many arguments for typing.Callable[~P, typing.Tuple[*Ts]]; actual 3, expected 2

The same for the C implementation (types.GenericAlias):

import collections.abc
C = collections.abc.Callable[P, Tuple[*Ts]]
C[[int], str, bytes]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/serhiy/py/cpython3.11/Lib/_collections_abc.py", line 468, in __getitem__
    new_args = super().__getitem__(item).__args__
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1229, in __typing_prepare_subst__
    return _prepare_paramspec_params(alias, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 297, in _prepare_paramspec_params
    _check_generic(cls, params, len(cls.__parameters__))
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 274, in _check_generic
    raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"
TypeError: Too many arguments for collections.abc.Callable[~P, typing.Tuple[*Ts]]; actual 3, expected 2

And for user generics:

T = TypeVar('T')
class A(Generic[P, T]):
    pass

B = A[P, Tuple[*Ts]]
B[[int], str, bytes]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 363, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1393, in __getitem__
    new_args = self._determine_new_args(args)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1417, in _determine_new_args
    args = prepare(self, args)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 1229, in __typing_prepare_subst__
    return _prepare_paramspec_params(alias, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 297, in _prepare_paramspec_params
    _check_generic(cls, params, len(cls.__parameters__))
  File "/home/serhiy/py/cpython3.11/Lib/typing.py", line 274, in _check_generic
    raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};"
TypeError: Too many arguments for __main__.A[~P, typing.Tuple[*Ts]]; actual 3, expected 2

But it works if ParamSpec and TypeVarTuple are in different order:

class A(Generic[T, P]):
    pass

B = A[Tuple[*Ts], P]
B[str, bytes, [int]]

It is a different bug than #99344 because it happens when you substitute in a generic alias instead of a user generic.

Activity

  1. added a commit that references this issue on Nov 12, 2022
  2. added a commit that references this issue on Nov 29, 2022
  3. added 3 commits that reference this issue on Nov 29, 2022
  4. AlexWaygood commented on Apr 10, 2023

    @AlexWaygood
    Member

    These examples all work fine on main and on 3.11.2. It looks like they were fixed by #99412, and appropriate tests were added. Is there anything more to do here?

  5. added
    pendingThe issue will be closed if no feedback is provided
    on Apr 10, 2023
  6. AlexWaygood commented on May 20, 2023

    @AlexWaygood
    Member

    Closing as "completed", since this was buggy in the past, but the bug was fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

3.11only security fixes3.12only security fixespendingThe issue will be closed if no feedback is providedtopic-typingtype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions