diff --git a/pytype/matcher.py b/pytype/matcher.py index 34d1e93a2..c9660c5ab 100644 --- a/pytype/matcher.py +++ b/pytype/matcher.py @@ -757,6 +757,11 @@ def _check_type_param_consistency( for old_value in old_concrete_values: if self._satisfies_common_superclass([new_value, old_value]): has_error = False + elif isinstance(old_value, function.ParamSpecMatch): + # TODO - Technically we need to check the type parameter against + # ParamSpec to check case the restrictions are different, but it + # seems we don't have the machinery to check that yet in pytype. + has_error = False elif old_value.cls.is_protocol: with self._track_partially_matched_protocols(): protocol_subst = datatypes.AliasingDict(subst) diff --git a/pytype/tests/test_typevar2.py b/pytype/tests/test_typevar2.py index 9fb164c6a..fa5e69e95 100644 --- a/pytype/tests/test_typevar2.py +++ b/pytype/tests/test_typevar2.py @@ -1217,6 +1217,23 @@ def f(self, x: T) -> T: return x """) + def test_check_type_param_against_param_spec(self): + self.Check(""" + import multiprocessing.pool + from typing import Callable, ParamSpec, TypeVar, Any + _T = TypeVar('_T') + _Args = ParamSpec('_Args') + + def decorator() -> Callable[[Callable[_Args, _T]], Callable[_Args, _T]]: + pass # pytype: disable=bad-return-type + def foo(): + @decorator() + def f(i: int): + return i + with multiprocessing.pool.ThreadPool(10) as pool: + a: list[Any] = pool.map(f, list(range(10))) # TODO: Should be list[int] + """) + if __name__ == "__main__": test_base.main()