@@ -222,6 +222,7 @@ class NewSemanticAnalyzer(NodeVisitor[None],
222
222
# not be found in phase 1, for example due to * imports.
223
223
errors = None # type: Errors # Keeps track of generated errors
224
224
plugin = None # type: Plugin # Mypy plugin for special casing of library features
225
+ statement = None # type: Node # Statement/definition being analyzed
225
226
226
227
def __init__ (self ,
227
228
modules : Dict [str , MypyFile ],
@@ -510,6 +511,7 @@ def file_context(self,
510
511
#
511
512
512
513
def visit_func_def (self , defn : FuncDef ) -> None :
514
+ self .statement = defn
513
515
defn .is_conditional = self .block_depth [- 1 ] > 0
514
516
515
517
# 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)
629
631
fun_type .variables = a .bind_function_type_variables (fun_type , defn )
630
632
631
633
def visit_overloaded_func_def (self , defn : OverloadedFuncDef ) -> None :
634
+ self .statement = defn
632
635
self .add_function_to_symbol_table (defn )
633
636
634
637
if not self .recurse_into_functions :
@@ -904,6 +907,7 @@ def check_function_signature(self, fdef: FuncItem) -> None:
904
907
self .fail ('Type signature has too many arguments' , fdef , blocker = True )
905
908
906
909
def visit_decorator (self , dec : Decorator ) -> None :
910
+ self .statement = dec
907
911
dec .func .is_conditional = self .block_depth [- 1 ] > 0
908
912
if not dec .is_overload :
909
913
self .add_symbol (dec .name (), dec , dec )
@@ -977,6 +981,7 @@ def check_decorated_function_is_method(self, decorator: str,
977
981
#
978
982
979
983
def visit_class_def (self , defn : ClassDef ) -> None :
984
+ self .statement = defn
980
985
with self .tvar_scope_frame (self .tvar_scope .class_frame ()):
981
986
self .analyze_class (defn )
982
987
@@ -1841,6 +1846,7 @@ def visit_import_all(self, i: ImportAll) -> None:
1841
1846
#
1842
1847
1843
1848
def visit_assignment_stmt (self , s : AssignmentStmt ) -> None :
1849
+ self .statement = s
1844
1850
tag = self .track_incomplete_refs ()
1845
1851
s .rvalue .accept (self )
1846
1852
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:
2403
2409
alias_node .normalized = rvalue .node .normalized
2404
2410
return True
2405
2411
2406
- def analyze_lvalue (self , lval : Lvalue , nested : bool = False ,
2412
+ def analyze_lvalue (self ,
2413
+ lval : Lvalue ,
2414
+ nested : bool = False ,
2407
2415
explicit_type : bool = False ,
2408
2416
is_final : bool = False ) -> None :
2409
2417
"""Analyze an lvalue or assignment target.
@@ -2484,7 +2492,6 @@ def analyze_name_lvalue(self,
2484
2492
self .fail ("Cannot redefine an existing name as final" , lvalue )
2485
2493
else :
2486
2494
self .make_name_lvalue_point_to_existing_def (lvalue , explicit_type , is_final )
2487
- # TODO: Special case local '_' assignment to always infer 'Any'
2488
2495
2489
2496
def is_final_redefinition (self , kind : int , name : str ) -> bool :
2490
2497
if kind == GDEF :
@@ -2540,30 +2547,25 @@ def make_name_lvalue_point_to_existing_def(
2540
2547
"""Update an lvalue to point to existing definition in the same scope.
2541
2548
2542
2549
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
2557
2550
2558
- # Redefining an existing name with final is always an error.
2551
+ Assume that an existing name exists.
2552
+ """
2559
2553
if is_final :
2554
+ # Redefining an existing name with final is always an error.
2560
2555
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 )
2561
2560
if explicit_type :
2562
- # Don't re-bind types
2561
+ # Don't re-bind if there is a type annotation.
2563
2562
self .name_already_defined (lval .name , lval , original_def )
2564
2563
else :
2565
2564
# 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 )
2567
2569
self .check_lvalue_validity (lval .node , lval )
2568
2570
2569
2571
def analyze_tuple_or_list_lvalue (self , lval : TupleExpr ,
@@ -2984,7 +2986,7 @@ def process_module_assignment(self, lvals: List[Lvalue], rval: Expression,
2984
2986
# respect explicitly annotated type
2985
2987
if (isinstance (lval .node , Var ) and lval .node .type is not None ):
2986
2988
continue
2987
- lnode = self .lookup ( lval .name , ctx )
2989
+ lnode = self .current_symbol_table (). get ( lval .name )
2988
2990
if lnode :
2989
2991
if isinstance (lnode .node , MypyFile ) and lnode .node is not rnode .node :
2990
2992
self .fail (
@@ -3020,42 +3022,49 @@ def visit_block_maybe(self, b: Optional[Block]) -> None:
3020
3022
self .visit_block (b )
3021
3023
3022
3024
def visit_expression_stmt (self , s : ExpressionStmt ) -> None :
3025
+ self .statement = s
3023
3026
s .expr .accept (self )
3024
3027
3025
3028
def visit_return_stmt (self , s : ReturnStmt ) -> None :
3029
+ self .statement = s
3026
3030
if not self .is_func_scope ():
3027
3031
self .fail ("'return' outside function" , s )
3028
3032
if s .expr :
3029
3033
s .expr .accept (self )
3030
3034
3031
3035
def visit_raise_stmt (self , s : RaiseStmt ) -> None :
3036
+ self .statement = s
3032
3037
if s .expr :
3033
3038
s .expr .accept (self )
3034
3039
if s .from_expr :
3035
3040
s .from_expr .accept (self )
3036
3041
3037
3042
def visit_assert_stmt (self , s : AssertStmt ) -> None :
3043
+ self .statement = s
3038
3044
if s .expr :
3039
3045
s .expr .accept (self )
3040
3046
if s .msg :
3041
3047
s .msg .accept (self )
3042
3048
3043
3049
def visit_operator_assignment_stmt (self ,
3044
3050
s : OperatorAssignmentStmt ) -> None :
3051
+ self .statement = s
3045
3052
s .lvalue .accept (self )
3046
3053
s .rvalue .accept (self )
3047
3054
if (isinstance (s .lvalue , NameExpr ) and s .lvalue .name == '__all__' and
3048
3055
s .lvalue .kind == GDEF and isinstance (s .rvalue , (ListExpr , TupleExpr ))):
3049
3056
self .add_exports (s .rvalue .items )
3050
3057
3051
3058
def visit_while_stmt (self , s : WhileStmt ) -> None :
3059
+ self .statement = s
3052
3060
s .expr .accept (self )
3053
3061
self .loop_depth += 1
3054
3062
s .body .accept (self )
3055
3063
self .loop_depth -= 1
3056
3064
self .visit_block_maybe (s .else_body )
3057
3065
3058
3066
def visit_for_stmt (self , s : ForStmt ) -> None :
3067
+ self .statement = s
3059
3068
s .expr .accept (self )
3060
3069
3061
3070
# Bind index variables and check if they define new names.
@@ -3076,21 +3085,25 @@ def visit_for_stmt(self, s: ForStmt) -> None:
3076
3085
self .visit_block_maybe (s .else_body )
3077
3086
3078
3087
def visit_break_stmt (self , s : BreakStmt ) -> None :
3088
+ self .statement = s
3079
3089
if self .loop_depth == 0 :
3080
3090
self .fail ("'break' outside loop" , s , True , blocker = True )
3081
3091
3082
3092
def visit_continue_stmt (self , s : ContinueStmt ) -> None :
3093
+ self .statement = s
3083
3094
if self .loop_depth == 0 :
3084
3095
self .fail ("'continue' outside loop" , s , True , blocker = True )
3085
3096
3086
3097
def visit_if_stmt (self , s : IfStmt ) -> None :
3098
+ self .statement = s
3087
3099
infer_reachability_of_if_statement (s , self .options )
3088
3100
for i in range (len (s .expr )):
3089
3101
s .expr [i ].accept (self )
3090
3102
self .visit_block (s .body [i ])
3091
3103
self .visit_block_maybe (s .else_body )
3092
3104
3093
3105
def visit_try_stmt (self , s : TryStmt ) -> None :
3106
+ self .statement = s
3094
3107
self .analyze_try_stmt (s , self )
3095
3108
3096
3109
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:
3107
3120
s .finally_body .accept (visitor )
3108
3121
3109
3122
def visit_with_stmt (self , s : WithStmt ) -> None :
3123
+ self .statement = s
3110
3124
types = [] # type: List[Type]
3111
3125
3112
3126
if s .unanalyzed_type :
@@ -3151,6 +3165,7 @@ def visit_with_stmt(self, s: WithStmt) -> None:
3151
3165
self .visit_block (s .body )
3152
3166
3153
3167
def visit_del_stmt (self , s : DelStmt ) -> None :
3168
+ self .statement = s
3154
3169
s .expr .accept (self )
3155
3170
if not self .is_valid_del_target (s .expr ):
3156
3171
self .fail ('Invalid delete target' , s )
@@ -3164,12 +3179,14 @@ def is_valid_del_target(self, s: Expression) -> bool:
3164
3179
return False
3165
3180
3166
3181
def visit_global_decl (self , g : GlobalDecl ) -> None :
3182
+ self .statement = g
3167
3183
for name in g .names :
3168
3184
if name in self .nonlocal_decls [- 1 ]:
3169
3185
self .fail ("Name '{}' is nonlocal and global" .format (name ), g )
3170
3186
self .global_decls [- 1 ].add (name )
3171
3187
3172
3188
def visit_nonlocal_decl (self , d : NonlocalDecl ) -> None :
3189
+ self .statement = d
3173
3190
if not self .is_func_scope ():
3174
3191
self .fail ("nonlocal declaration not allowed at module level" , d )
3175
3192
else :
@@ -3189,12 +3206,14 @@ def visit_nonlocal_decl(self, d: NonlocalDecl) -> None:
3189
3206
self .nonlocal_decls [- 1 ].add (name )
3190
3207
3191
3208
def visit_print_stmt (self , s : PrintStmt ) -> None :
3209
+ self .statement = s
3192
3210
for arg in s .args :
3193
3211
arg .accept (self )
3194
3212
if s .target :
3195
3213
s .target .accept (self )
3196
3214
3197
3215
def visit_exec_stmt (self , s : ExecStmt ) -> None :
3216
+ self .statement = s
3198
3217
s .expr .accept (self )
3199
3218
if s .globals :
3200
3219
s .globals .accept (self )
@@ -3208,15 +3227,19 @@ def visit_exec_stmt(self, s: ExecStmt) -> None:
3208
3227
def visit_name_expr (self , expr : NameExpr ) -> None :
3209
3228
n = self .lookup (expr .name , expr )
3210
3229
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
3220
3243
3221
3244
def visit_super_expr (self , expr : SuperExpr ) -> None :
3222
3245
if not self .type :
@@ -3731,9 +3754,25 @@ def lookup(self, name: str, ctx: Context,
3731
3754
if self .type and not self .is_func_scope () and name in self .type .names :
3732
3755
node = self .type .names [name ]
3733
3756
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
3737
3776
# 3. Local (function) scopes
3738
3777
for table in reversed (self .locals ):
3739
3778
if table is not None and name in table :
0 commit comments