|
30 | 30 | from mypy.types import (
|
31 | 31 | Type, AnyType, CallableType, Void, FunctionLike, Overloaded, TupleType,
|
32 | 32 | Instance, NoneTyp, ErrorType, strip_type,
|
33 |
| - UnionType, TypeVarType, PartialType, DeletedType |
| 33 | + UnionType, TypeVarType, PartialType, DeletedType, |
| 34 | + TypeQuery, ANY_TYPE_STRATEGY |
34 | 35 | )
|
35 | 36 | from mypy.sametypes import is_same_type
|
36 | 37 | from mypy.messages import MessageBuilder
|
@@ -353,6 +354,9 @@ class TypeChecker(NodeVisitor[Type]):
|
353 | 354 | dynamic_funcs = None # type: List[bool]
|
354 | 355 | # Stack of functions being type checked
|
355 | 356 | function_stack = None # type: List[FuncItem]
|
| 357 | + # Bound type variables (type parameters of surrounding generic |
| 358 | + # classes and functions) |
| 359 | + bound_tvars = set() # type: Set[int] |
356 | 360 | # Set to True on return/break/raise, False on blocks that can block any of them
|
357 | 361 | breaking_out = False
|
358 | 362 | # Do weak type checking in this file
|
@@ -396,6 +400,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile],
|
396 | 400 | self.type_context = []
|
397 | 401 | self.dynamic_funcs = []
|
398 | 402 | self.function_stack = []
|
| 403 | + self.bound_tvars = set() # type: Set[int] |
399 | 404 | self.weak_opts = set() # type: Set[str]
|
400 | 405 | self.partial_types = []
|
401 | 406 | self.deferred_nodes = []
|
@@ -458,6 +463,10 @@ def accept(self, node: Node, type_context: Type = None) -> Type:
|
458 | 463 | self.type_context.append(type_context)
|
459 | 464 | try:
|
460 | 465 | typ = node.accept(self)
|
| 466 | + if not only_has_type_vars(typ, self.bound_tvars): |
| 467 | + # This is really an internal mypy error, not a type error. |
| 468 | + # But it's more convenient to let mypy continue... |
| 469 | + self.fail('Unexpected free type variable in {}'.format(typ), node) |
461 | 470 | except Exception as err:
|
462 | 471 | report_internal_error(err, self.errors.file, node.line)
|
463 | 472 | self.type_context.pop()
|
@@ -648,6 +657,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None:
|
648 | 657 | old_binder = self.binder
|
649 | 658 | self.binder = ConditionalTypeBinder()
|
650 | 659 | self.binder.push_frame()
|
| 660 | + self.bound_tvars |= set(typ.type_var_ids()) |
651 | 661 | defn.expanded.append(item)
|
652 | 662 |
|
653 | 663 | # We may be checking a function definition or an anonymous
|
@@ -740,6 +750,7 @@ def is_implicit_any(t: Type) -> bool:
|
740 | 750 |
|
741 | 751 | self.return_types.pop()
|
742 | 752 |
|
| 753 | + self.bound_tvars -= set(typ.type_var_ids()) |
743 | 754 | self.binder = old_binder
|
744 | 755 |
|
745 | 756 | def check_reverse_op_method(self, defn: FuncItem, typ: CallableType,
|
@@ -1034,7 +1045,9 @@ def visit_class_def(self, defn: ClassDef) -> Type:
|
1034 | 1045 | old_binder = self.binder
|
1035 | 1046 | self.binder = ConditionalTypeBinder()
|
1036 | 1047 | self.binder.push_frame()
|
| 1048 | + self.bound_tvars |= set(tv.id for tv in defn.type_vars) |
1037 | 1049 | self.accept(defn.defs)
|
| 1050 | + self.bound_tvars -= set(tv.id for tv in defn.type_vars) |
1038 | 1051 | self.binder = old_binder
|
1039 | 1052 | self.check_multiple_inheritance(typ)
|
1040 | 1053 | self.leave_partial_types()
|
@@ -2549,3 +2562,25 @@ def is_valid_inferred_type(typ: Type) -> bool:
|
2549 | 2562 | if not is_valid_inferred_type(item):
|
2550 | 2563 | return False
|
2551 | 2564 | return True
|
| 2565 | + |
| 2566 | + |
| 2567 | +def only_has_type_vars(typ: Type, allowed_tvars: Set[int]) -> bool: |
| 2568 | + if typ is None: |
| 2569 | + return True |
| 2570 | + return not typ.accept(UnboundTypeVarVisitor(allowed_tvars)) |
| 2571 | + |
| 2572 | + |
| 2573 | +class UnboundTypeVarVisitor(TypeQuery): |
| 2574 | + allowed_tvars = set() # type: Set[int] |
| 2575 | + |
| 2576 | + def __init__(self, allowed_tvars: Set[int]) -> None: |
| 2577 | + super().__init__(False, ANY_TYPE_STRATEGY) |
| 2578 | + self.allowed_tvars = allowed_tvars |
| 2579 | + |
| 2580 | + def visit_type_var(self, t: TypeVarType) -> bool: |
| 2581 | + return t.id not in self.allowed_tvars |
| 2582 | + |
| 2583 | + def visit_callable_type(self, t: CallableType) -> bool: |
| 2584 | + # Bind the generic type variables of t |
| 2585 | + new_visitor = UnboundTypeVarVisitor(self.allowed_tvars | set(t.type_var_ids())) |
| 2586 | + return new_visitor.query_types(t.arg_types + [t.ret_type]) |
0 commit comments