Skip to content
Merged
Prev Previous commit
typeanal: add hint for correct usage of ParamSpec
  • Loading branch information
hauntsaninja
hauntsaninja committed Sep 7, 2020
commit 465113a334bccc200ba6a520a24dc8e36dd3a9e8
5 changes: 5 additions & 0 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
self.fail('ParamSpec "{}" is unbound'.format(t.name), t)
return AnyType(TypeOfAny.from_error)
self.fail('Invalid location for ParamSpec "{}"'.format(t.name), t)
self.note(
'You can use ParamSpec as the first argument to Callable, e.g., '
"'Callable[{}, int]'".format(t.name),
t
)
return AnyType(TypeOfAny.from_error)
if isinstance(sym.node, TypeVarExpr) and tvar_def is not None and self.defining_alias:
self.fail('Can\'t use bound type variable "{}"'
Expand Down
18 changes: 14 additions & 4 deletions test-data/unit/check-parameter-specification.test
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ from typing_extensions import ParamSpec, Concatenate
P = ParamSpec('P')

x: P # E: ParamSpec "P" is unbound

def foo1(x: Callable[P, int]) -> Callable[P, str]: ...
def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P"

def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P" \
# N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'

# TODO(shantanu): uncomment once we have support for Concatenate
# def foo3(x: Concatenate[int, P]) -> int: ... $ E: Invalid location for Concatenate
def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P"
def foo5(x: Callable[[int, str], P]) -> None: ... # E: Invalid location for ParamSpec "P"
def foo6(x: Callable[[P], int]) -> None: ... # E: Invalid location for ParamSpec "P"

def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P" \
# N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'

def foo5(x: Callable[[int, str], P]) -> None: ... # E: Invalid location for ParamSpec "P" \
# N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'

def foo6(x: Callable[[P], int]) -> None: ... # E: Invalid location for ParamSpec "P" \
# N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'
[builtins fixtures/tuple.pyi]