Skip to content

Commit

Permalink
Improve error message for callables with invalid Concatenate, refs p…
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Aug 26, 2022
1 parent da56c97 commit 1b9a5ec
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
18 changes: 15 additions & 3 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,8 +1026,10 @@ def analyze_callable_args_for_paramspec(
def analyze_callable_args_for_concatenate(
self, callable_args: Type, ret_type: Type, fallback: Instance
) -> CallableType | None:
"""Construct a 'Callable[C, RET]', where C is Concatenate[..., P], returning None if we
cannot.
"""Construct a 'Callable[C, RET]', where C is Concatenate[..., P]
Return `None` if we cannot.
Return `AnyType` if we only can do it partially.
"""
if not isinstance(callable_args, UnboundType):
return None
Expand All @@ -1039,7 +1041,17 @@ def analyze_callable_args_for_concatenate(
if sym.node.fullname not in ("typing_extensions.Concatenate", "typing.Concatenate"):
return None

tvar_def = self.anal_type(callable_args, allow_param_spec=True)
tvar_def = get_proper_type(self.anal_type(callable_args, allow_param_spec=True))
if isinstance(tvar_def, AnyType) and tvar_def.type_of_any == TypeOfAny.from_error:
# Some error happened, we won't be able to construct a proper type anyway.
# So, instead return a callable that accepts anything.
return CallableType(
arg_names=[None] * 2,
arg_types=[AnyType(TypeOfAny.from_error)] * 2,
arg_kinds=[ARG_STAR, ARG_STAR2],
ret_type=AnyType(TypeOfAny.from_error),
fallback=fallback,
)
if not isinstance(tvar_def, ParamSpecType):
return None

Expand Down
11 changes: 11 additions & 0 deletions test-data/unit/check-parameter-specification.test
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,17 @@ def f(x: int) -> None: ...
n.foo(f)
[builtins fixtures/paramspec.pyi]

[case testLastParameterToConcatenateAndInvalidCallable]
# See https://github.com/python/mypy/issues/13518
from typing_extensions import Concatenate, ParamSpec
from typing import Callable, TypeVar, Any

P = ParamSpec("P")

def f(fn: Callable[Concatenate[P, int], None]): ... # E: The last parameter to Concatenate needs to be a ParamSpec
reveal_type(f) # N: Revealed type is "def [P] (fn: def (*Any, **Any) -> Any) -> Any"
[builtins fixtures/paramspec.pyi]

[case testParamSpecLiteralsTypeApplication]
from typing_extensions import ParamSpec
from typing import Generic, Callable
Expand Down

0 comments on commit 1b9a5ec

Please sign in to comment.