@@ -3206,6 +3206,8 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
32063206 Handle all kinds of assignment statements (simple, indexed, multiple).
32073207 """
32083208
3209+ self .check_redundant_annotation (s )
3210+
32093211 # Avoid type checking type aliases in stubs to avoid false
32103212 # positives about modern type syntax available in stubs such
32113213 # as X | Y.
@@ -3258,6 +3260,32 @@ def check_type_alias_rvalue(self, s: AssignmentStmt) -> None:
32583260 alias_type = self .expr_checker .accept (s .rvalue )
32593261 self .store_type (s .lvalues [- 1 ], alias_type )
32603262
3263+ def check_redundant_annotation (self , s : AssignmentStmt ) -> None :
3264+ if (
3265+ self .options .warn_redundant_annotation
3266+ and not s .is_final_def
3267+ and not s .is_alias_def
3268+ and s .unanalyzed_type is not None
3269+ and s .type is not None
3270+ and not is_same_type (s .type , AnyType (TypeOfAny .special_form ))
3271+ and is_same_type (s .type , self .expr_checker .accept (s .rvalue ))
3272+ ):
3273+ # skip ClassVar
3274+ if any (
3275+ isinstance (lvalue , NameExpr )
3276+ and isinstance (lvalue .node , Var )
3277+ and lvalue .node .is_classvar
3278+ for lvalue in s .lvalues
3279+ ):
3280+ return
3281+
3282+ # skip dataclass and NamedTuple
3283+ cls = self .scope .active_class ()
3284+ if cls and (dataclasses_plugin .is_processed_dataclass (cls ) or cls .is_named_tuple ):
3285+ return
3286+
3287+ self .msg .redundant_annotation (s .type , s .rvalue )
3288+
32613289 def check_assignment (
32623290 self ,
32633291 lvalue : Lvalue ,
0 commit comments