24
24
DictionaryComprehension , ComplexExpr , EllipsisExpr , TypeAliasExpr ,
25
25
RefExpr , YieldExpr , BackquoteExpr , ImportFrom , ImportAll , ImportBase ,
26
26
AwaitExpr ,
27
- CONTRAVARIANT , COVARIANT
28
- )
29
- from mypy .nodes import function_type , method_type , method_type_with_fallback
27
+ CONTRAVARIANT , COVARIANT )
30
28
from mypy import nodes
31
29
from mypy .types import (
32
30
Type , AnyType , CallableType , Void , FunctionLike , Overloaded , TupleType ,
33
31
Instance , NoneTyp , ErrorType , strip_type ,
34
32
UnionType , TypeVarId , TypeVarType , PartialType , DeletedType , UninhabitedType ,
35
- true_only , false_only
33
+ true_only , false_only , function_type
36
34
)
37
35
from mypy .sametypes import is_same_type
38
36
from mypy .messages import MessageBuilder
39
37
import mypy .checkexpr
40
- from mypy .checkmember import map_type_from_supertype
38
+ from mypy .checkmember import map_type_from_supertype , bind_self
41
39
from mypy import messages
42
40
from mypy .subtypes import (
43
- is_subtype , is_equivalent , is_proper_subtype ,
44
- is_more_precise , restrict_subtype_away
41
+ is_subtype , is_equivalent , is_proper_subtype , is_more_precise , restrict_subtype_away
45
42
)
46
43
from mypy .maptype import map_instance_to_supertype
47
- from mypy .semanal import self_type , set_callable_name , refers_to_fullname
44
+ from mypy .semanal import fill_typevars , set_callable_name , refers_to_fullname
48
45
from mypy .erasetype import erase_typevars
49
46
from mypy .expandtype import expand_type
50
47
from mypy .visitor import NodeVisitor
@@ -93,6 +90,11 @@ class TypeChecker(NodeVisitor[Type]):
93
90
# Helper for type checking expressions
94
91
expr_checker = None # type: mypy.checkexpr.ExpressionChecker
95
92
93
+ # Class context for checking overriding of a method of the form
94
+ # def foo(self: T) -> T
95
+ # We need to pass the current class definition for instantiation of T
96
+ class_context = None # type: List[Type]
97
+
96
98
# Stack of function return types
97
99
return_types = None # type: List[Type]
98
100
# Type context for type inference
@@ -136,6 +138,7 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option
136
138
self .path = path
137
139
self .msg = MessageBuilder (errors , modules )
138
140
self .expr_checker = mypy .checkexpr .ExpressionChecker (self , self .msg )
141
+ self .class_context = []
139
142
self .binder = ConditionalTypeBinder ()
140
143
self .globals = tree .names
141
144
self .return_types = []
@@ -602,11 +605,13 @@ def is_implicit_any(t: Type) -> bool:
602
605
arg_type = typ .arg_types [i ]
603
606
604
607
# Refuse covariant parameter type variables
608
+ # TODO: check recuresively for inner type variables
605
609
if isinstance (arg_type , TypeVarType ):
606
- if arg_type .variance == COVARIANT :
607
- self .fail (messages .FUNCTION_PARAMETER_CANNOT_BE_COVARIANT ,
608
- arg_type )
609
-
610
+ if i > 0 :
611
+ if arg_type .variance == COVARIANT :
612
+ self .fail (messages .FUNCTION_PARAMETER_CANNOT_BE_COVARIANT ,
613
+ arg_type )
614
+ # FIX: if i == 0 and this is not a method then same as above
610
615
if typ .arg_kinds [i ] == nodes .ARG_STAR :
611
616
# builtins.tuple[T] is typing.Tuple[T, ...]
612
617
arg_type = self .named_generic_type ('builtins.tuple' ,
@@ -788,11 +793,11 @@ def check_inplace_operator_method(self, defn: FuncBase) -> None:
788
793
method = defn .name ()
789
794
if method not in nodes .inplace_operator_methods :
790
795
return
791
- typ = self .method_type (defn )
796
+ typ = bind_self ( self .function_type (defn ) )
792
797
cls = defn .info
793
798
other_method = '__' + method [3 :]
794
799
if cls .has_readable_member (other_method ):
795
- instance = self_type (cls )
800
+ instance = fill_typevars (cls )
796
801
typ2 = self .expr_checker .analyze_external_member_access (
797
802
other_method , instance , defn )
798
803
fail = False
@@ -868,7 +873,7 @@ def check_method_override_for_base_with_name(
868
873
# The name of the method is defined in the base class.
869
874
870
875
# Construct the type of the overriding method.
871
- typ = self .method_type (defn )
876
+ typ = bind_self ( self .function_type (defn ), self . class_context [ - 1 ] )
872
877
# Map the overridden method type to subtype context so that
873
878
# it can be checked for compatibility.
874
879
original_type = base_attr .type
@@ -881,7 +886,7 @@ def check_method_override_for_base_with_name(
881
886
assert False , str (base_attr .node )
882
887
if isinstance (original_type , FunctionLike ):
883
888
original = map_type_from_supertype (
884
- method_type (original_type ),
889
+ bind_self (original_type , self . class_context [ - 1 ] ),
885
890
defn .info , base )
886
891
# Check that the types are compatible.
887
892
# TODO overloaded signatures
@@ -965,7 +970,9 @@ def visit_class_def(self, defn: ClassDef) -> Type:
965
970
old_binder = self .binder
966
971
self .binder = ConditionalTypeBinder ()
967
972
with self .binder .top_frame_context ():
973
+ self .class_context .append (fill_typevars (defn .info ))
968
974
self .accept (defn .defs )
975
+ self .class_context .pop ()
969
976
self .binder = old_binder
970
977
if not defn .has_incompatible_baseclass :
971
978
# Otherwise we've already found errors; more errors are not useful
@@ -1012,8 +1019,8 @@ def check_compatibility(self, name: str, base1: TypeInfo,
1012
1019
if (isinstance (first_type , FunctionLike ) and
1013
1020
isinstance (second_type , FunctionLike )):
1014
1021
# Method override
1015
- first_sig = method_type (first_type )
1016
- second_sig = method_type (second_type )
1022
+ first_sig = bind_self (first_type )
1023
+ second_sig = bind_self (second_type )
1017
1024
ok = is_subtype (first_sig , second_sig )
1018
1025
elif first_type and second_type :
1019
1026
ok = is_equivalent (first_type , second_type )
@@ -2335,9 +2342,6 @@ def iterable_item_type(self, instance: Instance) -> Type:
2335
2342
def function_type (self , func : FuncBase ) -> FunctionLike :
2336
2343
return function_type (func , self .named_type ('builtins.function' ))
2337
2344
2338
- def method_type (self , func : FuncBase ) -> FunctionLike :
2339
- return method_type_with_fallback (func , self .named_type ('builtins.function' ))
2340
-
2341
2345
# TODO: These next two functions should refer to TypeMap below
2342
2346
def find_isinstance_check (self , n : Expression ) -> Tuple [Optional [Dict [Expression , Type ]],
2343
2347
Optional [Dict [Expression , Type ]]]:
@@ -2350,7 +2354,6 @@ def push_type_map(self, type_map: Optional[Dict[Expression, Type]]) -> None:
2350
2354
for expr , type in type_map .items ():
2351
2355
self .binder .push (expr , type )
2352
2356
2353
-
2354
2357
# Data structure returned by find_isinstance_check representing
2355
2358
# information learned from the truth or falsehood of a condition. The
2356
2359
# dict maps nodes representing expressions like 'a[0].x' to their
0 commit comments