221
221
# Maximum length of fixed tuple types inferred when narrowing from variadic tuples.
222
222
MAX_PRECISE_TUPLE_SIZE : Final = 8
223
223
224
- DeferredNodeType : _TypeAlias = Union [FuncDef , LambdaExpr , OverloadedFuncDef , Decorator ]
224
+ DeferredNodeType : _TypeAlias = Union [FuncDef , OverloadedFuncDef , Decorator ]
225
225
FineGrainedDeferredNodeType : _TypeAlias = Union [FuncDef , MypyFile , OverloadedFuncDef ]
226
226
227
227
228
228
# A node which is postponed to be processed during the next pass.
229
229
# In normal mode one can defer functions and methods (also decorated and/or overloaded)
230
- # and lambda expressions. Nested functions can't be deferred -- only top-level functions
230
+ # but not lambda expressions. Nested functions can't be deferred -- only top-level functions
231
231
# and methods of classes not defined within a function can be deferred.
232
232
class DeferredNode (NamedTuple ):
233
233
node : DeferredNodeType
234
- # And its TypeInfo (for semantic analysis self type handling
234
+ # And its TypeInfo (for semantic analysis self type handling)
235
235
active_typeinfo : TypeInfo | None
236
236
237
237
@@ -528,10 +528,7 @@ def check_partial(self, node: DeferredNodeType | FineGrainedDeferredNodeType) ->
528
528
else :
529
529
self .recurse_into_functions = True
530
530
with self .binder .top_frame_context ():
531
- if isinstance (node , LambdaExpr ):
532
- self .expr_checker .accept (node )
533
- else :
534
- self .accept (node )
531
+ self .accept (node )
535
532
536
533
def check_top_level (self , node : MypyFile ) -> None :
537
534
"""Check only the top-level of a module, skipping function definitions."""
@@ -558,13 +555,13 @@ def defer_node(self, node: DeferredNodeType, enclosing_class: TypeInfo | None) -
558
555
self .deferred_nodes .append (DeferredNode (node , enclosing_class ))
559
556
560
557
def handle_cannot_determine_type (self , name : str , context : Context ) -> None :
561
- node = self .scope .top_non_lambda_function ()
558
+ node = self .scope .top_level_function ()
562
559
if self .pass_num < self .last_pass and isinstance (node , FuncDef ):
563
560
# Don't report an error yet. Just defer. Note that we don't defer
564
561
# lambdas because they are coupled to the surrounding function
565
562
# through the binder and the inferred type of the lambda, so it
566
563
# would get messy.
567
- enclosing_class = self .scope .enclosing_class ()
564
+ enclosing_class = self .scope .enclosing_class (node )
568
565
self .defer_node (node , enclosing_class )
569
566
# Set a marker so that we won't infer additional types in this
570
567
# function. Any inferred types could be bogus, because there's at
@@ -2156,7 +2153,14 @@ def check_method_override_for_base_with_name(
2156
2153
if self .pass_num < self .last_pass :
2157
2154
# If there are passes left, defer this node until next pass,
2158
2155
# otherwise try reconstructing the method type from available information.
2159
- self .defer_node (defn , defn .info )
2156
+ # For consistency, defer an enclosing top-level function (if any).
2157
+ top_level = self .scope .top_level_function ()
2158
+ if isinstance (top_level , FuncDef ):
2159
+ self .defer_node (top_level , self .scope .enclosing_class (top_level ))
2160
+ else :
2161
+ # Specify enclosing class explicitly, as we check type override before
2162
+ # entering e.g. decorators or overloads.
2163
+ self .defer_node (defn , defn .info )
2160
2164
return True
2161
2165
elif isinstance (original_node , (FuncDef , OverloadedFuncDef )):
2162
2166
original_type = self .function_type (original_node )
@@ -4767,7 +4771,7 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
4767
4771
self .binder .unreachable ()
4768
4772
4769
4773
def check_return_stmt (self , s : ReturnStmt ) -> None :
4770
- defn = self .scope .top_function ()
4774
+ defn = self .scope .current_function ()
4771
4775
if defn is not None :
4772
4776
if defn .is_generator :
4773
4777
return_type = self .get_generator_return_type (
@@ -4779,7 +4783,7 @@ def check_return_stmt(self, s: ReturnStmt) -> None:
4779
4783
return_type = self .return_types [- 1 ]
4780
4784
return_type = get_proper_type (return_type )
4781
4785
4782
- is_lambda = isinstance (self . scope . top_function () , LambdaExpr )
4786
+ is_lambda = isinstance (defn , LambdaExpr )
4783
4787
if isinstance (return_type , UninhabitedType ):
4784
4788
# Avoid extra error messages for failed inference in lambdas
4785
4789
if not is_lambda and not return_type .ambiguous :
@@ -8554,14 +8558,15 @@ class CheckerScope:
8554
8558
def __init__ (self , module : MypyFile ) -> None :
8555
8559
self .stack = [module ]
8556
8560
8557
- def top_function (self ) -> FuncItem | None :
8561
+ def current_function (self ) -> FuncItem | None :
8558
8562
for e in reversed (self .stack ):
8559
8563
if isinstance (e , FuncItem ):
8560
8564
return e
8561
8565
return None
8562
8566
8563
- def top_non_lambda_function (self ) -> FuncItem | None :
8564
- for e in reversed (self .stack ):
8567
+ def top_level_function (self ) -> FuncItem | None :
8568
+ """Return top-level non-lambda function."""
8569
+ for e in self .stack :
8565
8570
if isinstance (e , FuncItem ) and not isinstance (e , LambdaExpr ):
8566
8571
return e
8567
8572
return None
@@ -8571,11 +8576,11 @@ def active_class(self) -> TypeInfo | None:
8571
8576
return self .stack [- 1 ]
8572
8577
return None
8573
8578
8574
- def enclosing_class (self ) -> TypeInfo | None :
8579
+ def enclosing_class (self , func : FuncItem | None = None ) -> TypeInfo | None :
8575
8580
"""Is there a class *directly* enclosing this function?"""
8576
- top = self .top_function ()
8577
- assert top , "This method must be called from inside a function"
8578
- index = self .stack .index (top )
8581
+ func = func or self .current_function ()
8582
+ assert func , "This method must be called from inside a function"
8583
+ index = self .stack .index (func )
8579
8584
assert index , "CheckerScope stack must always start with a module"
8580
8585
enclosing = self .stack [index - 1 ]
8581
8586
if isinstance (enclosing , TypeInfo ):
@@ -8589,7 +8594,7 @@ def active_self_type(self) -> Instance | TupleType | None:
8589
8594
In particular, inside a function nested in method this returns None.
8590
8595
"""
8591
8596
info = self .active_class ()
8592
- if not info and self .top_function ():
8597
+ if not info and self .current_function ():
8593
8598
info = self .enclosing_class ()
8594
8599
if info :
8595
8600
return fill_typevars (info )
0 commit comments