@@ -222,6 +222,7 @@ class NewSemanticAnalyzer(NodeVisitor[None],
222222 # not be found in phase 1, for example due to * imports.
223223 errors = None # type: Errors # Keeps track of generated errors
224224 plugin = None # type: Plugin # Mypy plugin for special casing of library features
225+ statement = None # type: Node # Statement/definition being analyzed
225226
226227 def __init__ (self ,
227228 modules : Dict [str , MypyFile ],
@@ -510,6 +511,7 @@ def file_context(self,
510511 #
511512
512513 def visit_func_def (self , defn : FuncDef ) -> None :
514+ self .statement = defn
513515 defn .is_conditional = self .block_depth [- 1 ] > 0
514516
515517 # Set full names even for those definitionss that aren't added
@@ -629,6 +631,7 @@ def update_function_type_variables(self, fun_type: CallableType, defn: FuncItem)
629631 fun_type .variables = a .bind_function_type_variables (fun_type , defn )
630632
631633 def visit_overloaded_func_def (self , defn : OverloadedFuncDef ) -> None :
634+ self .statement = defn
632635 self .add_function_to_symbol_table (defn )
633636
634637 if not self .recurse_into_functions :
@@ -904,6 +907,7 @@ def check_function_signature(self, fdef: FuncItem) -> None:
904907 self .fail ('Type signature has too many arguments' , fdef , blocker = True )
905908
906909 def visit_decorator (self , dec : Decorator ) -> None :
910+ self .statement = dec
907911 dec .func .is_conditional = self .block_depth [- 1 ] > 0
908912 if not dec .is_overload :
909913 self .add_symbol (dec .name (), dec , dec )
@@ -977,6 +981,7 @@ def check_decorated_function_is_method(self, decorator: str,
977981 #
978982
979983 def visit_class_def (self , defn : ClassDef ) -> None :
984+ self .statement = defn
980985 with self .tvar_scope_frame (self .tvar_scope .class_frame ()):
981986 self .analyze_class (defn )
982987
@@ -1841,6 +1846,7 @@ def visit_import_all(self, i: ImportAll) -> None:
18411846 #
18421847
18431848 def visit_assignment_stmt (self , s : AssignmentStmt ) -> None :
1849+ self .statement = s
18441850 tag = self .track_incomplete_refs ()
18451851 s .rvalue .accept (self )
18461852 if self .found_incomplete_ref (tag ) or self .should_wait_rhs (s .rvalue ):
@@ -2403,7 +2409,9 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool:
24032409 alias_node .normalized = rvalue .node .normalized
24042410 return True
24052411
2406- def analyze_lvalue (self , lval : Lvalue , nested : bool = False ,
2412+ def analyze_lvalue (self ,
2413+ lval : Lvalue ,
2414+ nested : bool = False ,
24072415 explicit_type : bool = False ,
24082416 is_final : bool = False ) -> None :
24092417 """Analyze an lvalue or assignment target.
@@ -2484,7 +2492,6 @@ def analyze_name_lvalue(self,
24842492 self .fail ("Cannot redefine an existing name as final" , lvalue )
24852493 else :
24862494 self .make_name_lvalue_point_to_existing_def (lvalue , explicit_type , is_final )
2487- # TODO: Special case local '_' assignment to always infer 'Any'
24882495
24892496 def is_final_redefinition (self , kind : int , name : str ) -> bool :
24902497 if kind == GDEF :
@@ -2540,30 +2547,25 @@ def make_name_lvalue_point_to_existing_def(
25402547 """Update an lvalue to point to existing definition in the same scope.
25412548
25422549 Arguments are similar to "analyze_lvalue".
2543- """
2544- # Assume that an existing name exists. Try to find the original definition.
2545- global_def = self .globals .get (lval .name )
2546- if self .locals :
2547- locals_last = self .locals [- 1 ]
2548- if locals_last :
2549- local_def = locals_last .get (lval .name )
2550- else :
2551- local_def = None
2552- else :
2553- local_def = None
2554- type_def = self .type .names .get (lval .name ) if self .type else None
2555-
2556- original_def = global_def or local_def or type_def
25572550
2558- # Redefining an existing name with final is always an error.
2551+ Assume that an existing name exists.
2552+ """
25592553 if is_final :
2554+ # Redefining an existing name with final is always an error.
25602555 self .fail ("Cannot redefine an existing name as final" , lval )
2556+ original_def = self .lookup (lval .name , lval , suppress_errors = True )
2557+ if original_def is None and self .type and not self .is_func_scope ():
2558+ # Workaround to allow "x, x = ..." in class body.
2559+ original_def = self .type .get (lval .name )
25612560 if explicit_type :
2562- # Don't re-bind types
2561+ # Don't re-bind if there is a type annotation.
25632562 self .name_already_defined (lval .name , lval , original_def )
25642563 else :
25652564 # Bind to an existing name.
2566- lval .accept (self )
2565+ if original_def :
2566+ self .bind_name_expr (lval , original_def )
2567+ else :
2568+ self .name_not_defined (lval .name , lval )
25672569 self .check_lvalue_validity (lval .node , lval )
25682570
25692571 def analyze_tuple_or_list_lvalue (self , lval : TupleExpr ,
@@ -2984,7 +2986,7 @@ def process_module_assignment(self, lvals: List[Lvalue], rval: Expression,
29842986 # respect explicitly annotated type
29852987 if (isinstance (lval .node , Var ) and lval .node .type is not None ):
29862988 continue
2987- lnode = self .lookup ( lval .name , ctx )
2989+ lnode = self .current_symbol_table (). get ( lval .name )
29882990 if lnode :
29892991 if isinstance (lnode .node , MypyFile ) and lnode .node is not rnode .node :
29902992 self .fail (
@@ -3020,42 +3022,49 @@ def visit_block_maybe(self, b: Optional[Block]) -> None:
30203022 self .visit_block (b )
30213023
30223024 def visit_expression_stmt (self , s : ExpressionStmt ) -> None :
3025+ self .statement = s
30233026 s .expr .accept (self )
30243027
30253028 def visit_return_stmt (self , s : ReturnStmt ) -> None :
3029+ self .statement = s
30263030 if not self .is_func_scope ():
30273031 self .fail ("'return' outside function" , s )
30283032 if s .expr :
30293033 s .expr .accept (self )
30303034
30313035 def visit_raise_stmt (self , s : RaiseStmt ) -> None :
3036+ self .statement = s
30323037 if s .expr :
30333038 s .expr .accept (self )
30343039 if s .from_expr :
30353040 s .from_expr .accept (self )
30363041
30373042 def visit_assert_stmt (self , s : AssertStmt ) -> None :
3043+ self .statement = s
30383044 if s .expr :
30393045 s .expr .accept (self )
30403046 if s .msg :
30413047 s .msg .accept (self )
30423048
30433049 def visit_operator_assignment_stmt (self ,
30443050 s : OperatorAssignmentStmt ) -> None :
3051+ self .statement = s
30453052 s .lvalue .accept (self )
30463053 s .rvalue .accept (self )
30473054 if (isinstance (s .lvalue , NameExpr ) and s .lvalue .name == '__all__' and
30483055 s .lvalue .kind == GDEF and isinstance (s .rvalue , (ListExpr , TupleExpr ))):
30493056 self .add_exports (s .rvalue .items )
30503057
30513058 def visit_while_stmt (self , s : WhileStmt ) -> None :
3059+ self .statement = s
30523060 s .expr .accept (self )
30533061 self .loop_depth += 1
30543062 s .body .accept (self )
30553063 self .loop_depth -= 1
30563064 self .visit_block_maybe (s .else_body )
30573065
30583066 def visit_for_stmt (self , s : ForStmt ) -> None :
3067+ self .statement = s
30593068 s .expr .accept (self )
30603069
30613070 # Bind index variables and check if they define new names.
@@ -3076,21 +3085,25 @@ def visit_for_stmt(self, s: ForStmt) -> None:
30763085 self .visit_block_maybe (s .else_body )
30773086
30783087 def visit_break_stmt (self , s : BreakStmt ) -> None :
3088+ self .statement = s
30793089 if self .loop_depth == 0 :
30803090 self .fail ("'break' outside loop" , s , True , blocker = True )
30813091
30823092 def visit_continue_stmt (self , s : ContinueStmt ) -> None :
3093+ self .statement = s
30833094 if self .loop_depth == 0 :
30843095 self .fail ("'continue' outside loop" , s , True , blocker = True )
30853096
30863097 def visit_if_stmt (self , s : IfStmt ) -> None :
3098+ self .statement = s
30873099 infer_reachability_of_if_statement (s , self .options )
30883100 for i in range (len (s .expr )):
30893101 s .expr [i ].accept (self )
30903102 self .visit_block (s .body [i ])
30913103 self .visit_block_maybe (s .else_body )
30923104
30933105 def visit_try_stmt (self , s : TryStmt ) -> None :
3106+ self .statement = s
30943107 self .analyze_try_stmt (s , self )
30953108
30963109 def analyze_try_stmt (self , s : TryStmt , visitor : NodeVisitor [None ]) -> None :
@@ -3107,6 +3120,7 @@ def analyze_try_stmt(self, s: TryStmt, visitor: NodeVisitor[None]) -> None:
31073120 s .finally_body .accept (visitor )
31083121
31093122 def visit_with_stmt (self , s : WithStmt ) -> None :
3123+ self .statement = s
31103124 types = [] # type: List[Type]
31113125
31123126 if s .unanalyzed_type :
@@ -3151,6 +3165,7 @@ def visit_with_stmt(self, s: WithStmt) -> None:
31513165 self .visit_block (s .body )
31523166
31533167 def visit_del_stmt (self , s : DelStmt ) -> None :
3168+ self .statement = s
31543169 s .expr .accept (self )
31553170 if not self .is_valid_del_target (s .expr ):
31563171 self .fail ('Invalid delete target' , s )
@@ -3164,12 +3179,14 @@ def is_valid_del_target(self, s: Expression) -> bool:
31643179 return False
31653180
31663181 def visit_global_decl (self , g : GlobalDecl ) -> None :
3182+ self .statement = g
31673183 for name in g .names :
31683184 if name in self .nonlocal_decls [- 1 ]:
31693185 self .fail ("Name '{}' is nonlocal and global" .format (name ), g )
31703186 self .global_decls [- 1 ].add (name )
31713187
31723188 def visit_nonlocal_decl (self , d : NonlocalDecl ) -> None :
3189+ self .statement = d
31733190 if not self .is_func_scope ():
31743191 self .fail ("nonlocal declaration not allowed at module level" , d )
31753192 else :
@@ -3189,12 +3206,14 @@ def visit_nonlocal_decl(self, d: NonlocalDecl) -> None:
31893206 self .nonlocal_decls [- 1 ].add (name )
31903207
31913208 def visit_print_stmt (self , s : PrintStmt ) -> None :
3209+ self .statement = s
31923210 for arg in s .args :
31933211 arg .accept (self )
31943212 if s .target :
31953213 s .target .accept (self )
31963214
31973215 def visit_exec_stmt (self , s : ExecStmt ) -> None :
3216+ self .statement = s
31983217 s .expr .accept (self )
31993218 if s .globals :
32003219 s .globals .accept (self )
@@ -3208,15 +3227,19 @@ def visit_exec_stmt(self, s: ExecStmt) -> None:
32083227 def visit_name_expr (self , expr : NameExpr ) -> None :
32093228 n = self .lookup (expr .name , expr )
32103229 if n :
3211- if isinstance (n .node , TypeVarExpr ) and self .tvar_scope .get_binding (n ):
3212- self .fail ("'{}' is a type variable and only valid in type "
3213- "context" .format (expr .name ), expr )
3214- elif isinstance (n .node , PlaceholderNode ):
3215- self .process_placeholder (expr .name , 'name' , expr )
3216- else :
3217- expr .kind = n .kind
3218- expr .node = n .node
3219- expr .fullname = n .fullname
3230+ self .bind_name_expr (expr , n )
3231+
3232+ def bind_name_expr (self , expr : NameExpr , sym : SymbolTableNode ) -> None :
3233+ """Bind name expression to a symbol table node."""
3234+ if isinstance (sym .node , TypeVarExpr ) and self .tvar_scope .get_binding (sym ):
3235+ self .fail ("'{}' is a type variable and only valid in type "
3236+ "context" .format (expr .name ), expr )
3237+ elif isinstance (sym .node , PlaceholderNode ):
3238+ self .process_placeholder (expr .name , 'name' , expr )
3239+ else :
3240+ expr .kind = sym .kind
3241+ expr .node = sym .node
3242+ expr .fullname = sym .fullname
32203243
32213244 def visit_super_expr (self , expr : SuperExpr ) -> None :
32223245 if not self .type :
@@ -3731,9 +3754,25 @@ def lookup(self, name: str, ctx: Context,
37313754 if self .type and not self .is_func_scope () and name in self .type .names :
37323755 node = self .type .names [name ]
37333756 if not node .implicit :
3734- return node
3735- implicit_name = True
3736- implicit_node = node
3757+ # Only allow access to class attributes textually after
3758+ # the definition, so that it's possible to fall back to the
3759+ # outer scope. Example:
3760+ #
3761+ # class X: ...
3762+ #
3763+ # class C:
3764+ # X = X # Initializer refers to outer scope
3765+ #
3766+ # Nested classes are an exception, since we want to support
3767+ # arbitrary forward references in type annotations.
3768+ if (node .node is None
3769+ or node .node .line < self .statement .line
3770+ or isinstance (node .node , TypeInfo )):
3771+ return node
3772+ else :
3773+ # Defined through self.x assignment
3774+ implicit_name = True
3775+ implicit_node = node
37373776 # 3. Local (function) scopes
37383777 for table in reversed (self .locals ):
37393778 if table is not None and name in table :
0 commit comments