Skip to content

Commit c7a80de

Browse files
author
hauntsaninja
committed
typeanal: error for invalid location for ParamSpec
1 parent 77dd1cd commit c7a80de

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

mypy/typeanal.py

+24-6
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
204204
if tvar_def is None:
205205
self.fail('ParamSpec "{}" is unbound'.format(t.name), t)
206206
return AnyType(TypeOfAny.from_error)
207+
self.fail('Invalid location for ParamSpec "{}"'.format(t.name), t)
208+
return AnyType(TypeOfAny.from_error)
207209
if isinstance(sym.node, TypeVarExpr) and tvar_def is not None and self.defining_alias:
208210
self.fail('Can\'t use bound type variable "{}"'
209211
' to define generic alias'.format(t.name), t)
@@ -624,10 +626,11 @@ def analyze_callable_type(self, t: UnboundType) -> Type:
624626
fallback=fallback,
625627
is_ellipsis_args=True)
626628
elif len(t.args) == 2:
629+
callable_args = t.args[0]
627630
ret_type = t.args[1]
628-
if isinstance(t.args[0], TypeList):
631+
if isinstance(callable_args, TypeList):
629632
# Callable[[ARG, ...], RET] (ordinary callable type)
630-
analyzed_args = self.analyze_callable_args(t.args[0])
633+
analyzed_args = self.analyze_callable_args(callable_args)
631634
if analyzed_args is None:
632635
return AnyType(TypeOfAny.from_error)
633636
args, kinds, names = analyzed_args
@@ -636,7 +639,7 @@ def analyze_callable_type(self, t: UnboundType) -> Type:
636639
names,
637640
ret_type=ret_type,
638641
fallback=fallback)
639-
elif isinstance(t.args[0], EllipsisType):
642+
elif isinstance(callable_args, EllipsisType):
640643
# Callable[..., RET] (with literal ellipsis; accept arbitrary arguments)
641644
ret = CallableType([AnyType(TypeOfAny.explicit),
642645
AnyType(TypeOfAny.explicit)],
@@ -646,8 +649,23 @@ def analyze_callable_type(self, t: UnboundType) -> Type:
646649
fallback=fallback,
647650
is_ellipsis_args=True)
648651
else:
649-
self.fail('The first argument to Callable must be a list of types or "..."', t)
650-
return AnyType(TypeOfAny.from_error)
652+
try:
653+
if not isinstance(callable_args, UnboundType):
654+
raise ValueError
655+
sym = self.lookup_qualified(callable_args.name, callable_args)
656+
if sym is None:
657+
raise ValueError
658+
tvar_def = self.tvar_scope.get_binding(sym)
659+
if not isinstance(tvar_def, ParamSpecDef):
660+
raise ValueError
661+
662+
# TODO(shantanu): construct correct type for paramspec
663+
return AnyType(TypeOfAny.from_error)
664+
except ValueError:
665+
# TODO(shantanu): change error to mention paramspec, once we actually have some
666+
# support for it
667+
self.fail('The first argument to Callable must be a list of types or "..."', t)
668+
return AnyType(TypeOfAny.from_error)
651669
else:
652670
self.fail('Please use "Callable[[<parameters>], <return type>]" or "Callable"', t)
653671
return AnyType(TypeOfAny.from_error)
@@ -828,7 +846,7 @@ def bind_function_type_variables(
828846
var_node = self.lookup_qualified(var.name, defn)
829847
assert var_node, "Binding for function type variable not found within function"
830848
var_expr = var_node.node
831-
assert isinstance(var_expr, TypeVarExpr)
849+
assert isinstance(var_expr, TypeVarLikeExpr)
832850
self.tvar_scope.bind_new(var.name, var_expr)
833851
return fun_type.variables
834852
typevars = self.infer_type_variables(fun_type)

0 commit comments

Comments
 (0)