From 807bd3990920271dddd64a368056c30f78dcba76 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Wed, 30 Aug 2023 03:08:05 +0100 Subject: [PATCH] Fix ParamSpec inference for callback protocols (#15986) Fixes https://github.com/python/mypy/issues/15984 Fix is straightforward, `ParamSpec` inference special-casing should put instances with `__call__` and callable types on same ground. --- mypy/checkexpr.py | 4 ++++ test-data/unit/check-parameter-specification.test | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 4430d0773cfa..218568007b9e 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2185,6 +2185,10 @@ def get_arg_infer_passes( # run(test, 1, 2) # we will use `test` for inference, since it will allow to infer also # argument *names* for P <: [x: int, y: int]. + if isinstance(p_actual, Instance): + call_method = find_member("__call__", p_actual, p_actual, is_operator=True) + if call_method is not None: + p_actual = get_proper_type(call_method) if ( isinstance(p_actual, CallableType) and not p_actual.variables diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index ed1d59b376d2..a98c92ce14e7 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1824,3 +1824,18 @@ class C(Generic[P]): ... c: C[int, [int, str], str] # E: Nested parameter specifications are not allowed reveal_type(c) # N: Revealed type is "__main__.C[Any]" [builtins fixtures/paramspec.pyi] + +[case testParamSpecInferenceWithCallbackProtocol] +from typing import Protocol, Callable, ParamSpec + +class CB(Protocol): + def __call__(self, x: str, y: int) -> None: ... + +P = ParamSpec('P') +def g(fn: Callable[P, None], *args: P.args, **kwargs: P.kwargs) -> None: ... + +cb: CB +g(cb, y=0, x='a') # OK +g(cb, y='a', x=0) # E: Argument "y" to "g" has incompatible type "str"; expected "int" \ + # E: Argument "x" to "g" has incompatible type "int"; expected "str" +[builtins fixtures/paramspec.pyi]