@@ -2563,6 +2563,11 @@ def analyze_member_lvalue(self, lval: MemberExpr, explicit_type: bool, is_final:
2563
2563
if cur_node and is_final :
2564
2564
# Overrides will be checked in type checker.
2565
2565
self .fail ("Cannot redefine an existing name as final" , lval )
2566
+ # On first encounter with this definition, if this attribute was defined before
2567
+ # with an inferred type and it's marked with an explicit type now, give an error.
2568
+ if (not lval .node and cur_node and isinstance (cur_node .node , Var ) and
2569
+ cur_node .node .is_inferred and explicit_type ):
2570
+ self .attribute_already_defined (lval .name , lval , cur_node )
2566
2571
# If the attribute of self is not defined in superclasses, create a new Var, ...
2567
2572
if ((node is None or isinstance (node .node , Var ) and node .node .is_abstract_var ) or
2568
2573
# ... also an explicit declaration on self also creates a new Var.
@@ -4298,9 +4303,9 @@ def name_not_defined(self, name: str, ctx: Context, namespace: Optional[str] = N
4298
4303
# Yes. Generate a helpful note.
4299
4304
self .add_fixture_note (fullname , ctx )
4300
4305
4301
- def name_already_defined (self , name : str , ctx : Context ,
4302
- original_ctx : Optional [Union [SymbolTableNode , SymbolNode ]] = None
4303
- ) -> None :
4306
+ def already_defined (self , name : str , ctx : Context ,
4307
+ original_ctx : Optional [Union [SymbolTableNode , SymbolNode ]] = None , * ,
4308
+ noun : str ) -> None :
4304
4309
if isinstance (original_ctx , SymbolTableNode ):
4305
4310
node = original_ctx .node # type: Optional[SymbolNode]
4306
4311
elif isinstance (original_ctx , SymbolNode ):
@@ -4319,7 +4324,17 @@ def name_already_defined(self, name: str, ctx: Context,
4319
4324
extra_msg = ' on line {}' .format (node .line )
4320
4325
else :
4321
4326
extra_msg = ' (possibly by an import)'
4322
- self .fail ("Name '{}' already defined{}" .format (unmangle (name ), extra_msg ), ctx )
4327
+ self .fail ("{} '{}' already defined{}" .format (noun , unmangle (name ), extra_msg ), ctx )
4328
+
4329
+ def name_already_defined (self , name : str , ctx : Context ,
4330
+ original_ctx : Optional [Union [SymbolTableNode , SymbolNode ]] = None
4331
+ ) -> None :
4332
+ self .already_defined (name , ctx , original_ctx , noun = 'Name' )
4333
+
4334
+ def attribute_already_defined (self , name : str , ctx : Context ,
4335
+ original_ctx : Optional [Union [SymbolTableNode , SymbolNode ]] = None
4336
+ ) -> None :
4337
+ self .already_defined (name , ctx , original_ctx , noun = 'Attribute' )
4323
4338
4324
4339
def is_local_name (self , name : str ) -> bool :
4325
4340
"""Does name look like reference to a definition in the current module?"""
0 commit comments