6565LAST_PASS = 1 # Pass numbers start at 0
6666
6767
68- # A node which is postponed to be type checked during the next pass.
68+ # A node which is postponed to be processed during the next pass.
69+ # This is used for both batch mode and fine-grained incremental mode.
6970DeferredNode = NamedTuple (
7071 'DeferredNode' ,
7172 [
72- ('node' , FuncItem ),
73+ # In batch mode only FuncDef and LambdaExpr are supported
74+ ('node' , Union [FuncDef , LambdaExpr , MypyFile ]),
7375 ('context_type_name' , Optional [str ]), # Name of the surrounding class (for error messages)
74- ('active_class' , Optional [Type ]), # And its type (for selftype handling)
76+ ('active_typeinfo' , Optional [TypeInfo ]), # And its TypeInfo (for semantic analysis
77+ # self type handling)
7578 ])
7679
7780
@@ -167,7 +170,7 @@ def check_first_pass(self) -> None:
167170
168171 Deferred functions will be processed by check_second_pass().
169172 """
170- self .errors .set_file (self .path )
173+ self .errors .set_file (self .path , self . tree . fullname () )
171174 with self .enter_partial_types ():
172175 with self .binder .top_frame_context ():
173176 for d in self .tree .defs :
@@ -187,38 +190,57 @@ def check_first_pass(self) -> None:
187190 self .fail (messages .ALL_MUST_BE_SEQ_STR .format (str_seq_s , all_s ),
188191 all_ .node )
189192
190- def check_second_pass (self ) -> bool :
193+ def check_second_pass (self , todo : List [ DeferredNode ] = None ) -> bool :
191194 """Run second or following pass of type checking.
192195
193196 This goes through deferred nodes, returning True if there were any.
194197 """
195- if not self .deferred_nodes :
198+ if not todo and not self .deferred_nodes :
196199 return False
197- self .errors .set_file (self .path )
200+ self .errors .set_file (self .path , self . tree . fullname () )
198201 self .pass_num += 1
199- todo = self .deferred_nodes
202+ if not todo :
203+ todo = self .deferred_nodes
204+ else :
205+ assert not self .deferred_nodes
200206 self .deferred_nodes = []
201- done = set () # type: Set[FuncItem ]
202- for node , type_name , active_class in todo :
207+ done = set () # type: Set[Union[FuncDef, LambdaExpr, MypyFile] ]
208+ for node , type_name , active_typeinfo in todo :
203209 if node in done :
204210 continue
205211 # This is useful for debugging:
206212 # print("XXX in pass %d, class %s, function %s" %
207213 # (self.pass_num, type_name, node.fullname() or node.name()))
208214 done .add (node )
209215 with self .errors .enter_type (type_name ) if type_name else nothing ():
210- with self .scope .push_class (active_class ) if active_class else nothing ():
211- if isinstance (node , Statement ):
212- self .accept (node )
213- elif isinstance (node , Expression ):
214- self .expr_checker .accept (node )
215- else :
216- assert False
216+ with self .scope .push_class (active_typeinfo ) if active_typeinfo else nothing ():
217+ self .check_partial (node )
217218 return True
218219
220+ def check_partial (self , node : Union [FuncDef , LambdaExpr , MypyFile ]) -> None :
221+ if isinstance (node , MypyFile ):
222+ self .check_top_level (node )
223+ elif isinstance (node , LambdaExpr ):
224+ self .expr_checker .accept (node )
225+ else :
226+ self .accept (node )
227+
228+ def check_top_level (self , node : MypyFile ) -> None :
229+ """Check only the top-level of a module, skipping function definitions."""
230+ with self .enter_partial_types ():
231+ with self .binder .top_frame_context ():
232+ for d in node .defs :
233+ # TODO: Type check class bodies.
234+ if not isinstance (d , (FuncDef , ClassDef )):
235+ d .accept (self )
236+
237+ assert not self .current_node_deferred
238+ # TODO: Handle __all__
239+
219240 def handle_cannot_determine_type (self , name : str , context : Context ) -> None :
220241 node = self .scope .top_function ()
221- if self .pass_num < LAST_PASS and node is not None :
242+ if (self .pass_num < LAST_PASS and node is not None
243+ and isinstance (node , (FuncDef , LambdaExpr ))):
222244 # Don't report an error yet. Just defer.
223245 if self .errors .type_name :
224246 type_name = self .errors .type_name [- 1 ]
@@ -635,7 +657,7 @@ def is_implicit_any(t: Type) -> bool:
635657 for i in range (len (typ .arg_types )):
636658 arg_type = typ .arg_types [i ]
637659
638- ref_type = self .scope .active_class ()
660+ ref_type = self .scope .active_self_type () # type: Optional[Type]
639661 if (isinstance (defn , FuncDef ) and ref_type is not None and i == 0
640662 and not defn .is_static
641663 and typ .arg_kinds [0 ] not in [nodes .ARG_STAR , nodes .ARG_STAR2 ]):
@@ -946,7 +968,7 @@ def check_method_override_for_base_with_name(
946968 # The name of the method is defined in the base class.
947969
948970 # Construct the type of the overriding method.
949- typ = bind_self (self .function_type (defn ), self .scope .active_class ())
971+ typ = bind_self (self .function_type (defn ), self .scope .active_self_type ())
950972 # Map the overridden method type to subtype context so that
951973 # it can be checked for compatibility.
952974 original_type = base_attr .type
@@ -959,7 +981,7 @@ def check_method_override_for_base_with_name(
959981 assert False , str (base_attr .node )
960982 if isinstance (original_type , FunctionLike ):
961983 original = map_type_from_supertype (
962- bind_self (original_type , self .scope .active_class ()),
984+ bind_self (original_type , self .scope .active_self_type ()),
963985 defn .info , base )
964986 # Check that the types are compatible.
965987 # TODO overloaded signatures
@@ -1051,7 +1073,7 @@ def visit_class_def(self, defn: ClassDef) -> None:
10511073 old_binder = self .binder
10521074 self .binder = ConditionalTypeBinder ()
10531075 with self .binder .top_frame_context ():
1054- with self .scope .push_class (fill_typevars ( defn .info ) ):
1076+ with self .scope .push_class (defn .info ):
10551077 self .accept (defn .defs )
10561078 self .binder = old_binder
10571079 if not defn .has_incompatible_baseclass :
@@ -1317,8 +1339,8 @@ def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Type, rvalue:
13171339 # Class-level function objects and classmethods become bound
13181340 # methods: the former to the instance, the latter to the
13191341 # class
1320- base_type = bind_self (base_type , self .scope .active_class ())
1321- compare_type = bind_self (compare_type , self .scope .active_class ())
1342+ base_type = bind_self (base_type , self .scope .active_self_type ())
1343+ compare_type = bind_self (compare_type , self .scope .active_self_type ())
13221344
13231345 # If we are a static method, ensure to also tell the
13241346 # lvalue it now contains a static method
@@ -1347,7 +1369,8 @@ def lvalue_type_from_base(self, expr_node: Var,
13471369
13481370 if base_type :
13491371 if not has_no_typevars (base_type ):
1350- instance = cast (Instance , self .scope .active_class ())
1372+ # TODO: Handle TupleType, don't cast
1373+ instance = cast (Instance , self .scope .active_self_type ())
13511374 itype = map_instance_to_supertype (instance , base )
13521375 base_type = expand_type_by_instance (base_type , itype )
13531376
@@ -2996,7 +3019,7 @@ def is_node_static(node: Node) -> Optional[bool]:
29963019
29973020class Scope :
29983021 # We keep two stacks combined, to maintain the relative order
2999- stack = None # type: List[Union[Type , FuncItem, MypyFile]]
3022+ stack = None # type: List[Union[TypeInfo , FuncItem, MypyFile]]
30003023
30013024 def __init__ (self , module : MypyFile ) -> None :
30023025 self .stack = [module ]
@@ -3007,20 +3030,26 @@ def top_function(self) -> Optional[FuncItem]:
30073030 return e
30083031 return None
30093032
3010- def active_class (self ) -> Optional [Type ]:
3011- if isinstance (self .stack [- 1 ], Type ):
3033+ def active_class (self ) -> Optional [TypeInfo ]:
3034+ if isinstance (self .stack [- 1 ], TypeInfo ):
30123035 return self .stack [- 1 ]
30133036 return None
30143037
3038+ def active_self_type (self ) -> Optional [Union [Instance , TupleType ]]:
3039+ info = self .active_class ()
3040+ if info :
3041+ return fill_typevars (info )
3042+ return None
3043+
30153044 @contextmanager
30163045 def push_function (self , item : FuncItem ) -> Iterator [None ]:
30173046 self .stack .append (item )
30183047 yield
30193048 self .stack .pop ()
30203049
30213050 @contextmanager
3022- def push_class (self , t : Type ) -> Iterator [None ]:
3023- self .stack .append (t )
3051+ def push_class (self , info : TypeInfo ) -> Iterator [None ]:
3052+ self .stack .append (info )
30243053 yield
30253054 self .stack .pop ()
30263055
0 commit comments