1- use crate :: utils:: span_lint_and_note;
1+ use crate :: utils:: { snippet , span_lint_and_note} ;
22use if_chain:: if_chain;
3- use rustc_ast_pretty :: pprust :: { expr_to_string , ty_to_string } ;
3+ use rustc_ast :: ast :: { BindingMode , Block , ExprKind , Mutability , PatKind , StmtKind } ;
44use rustc_lint:: { EarlyContext , EarlyLintPass } ;
55use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
66use rustc_span:: symbol:: Symbol ;
7- use syntax:: ast:: { BindingMode , Block , ExprKind , Mutability , PatKind , StmtKind } ;
87
98declare_clippy_lint ! {
109 /// **What it does:** Checks for immediate reassignment of fields initialized
@@ -39,6 +38,10 @@ declare_clippy_lint! {
3938
4039declare_lint_pass ! ( FieldReassignWithDefault => [ FIELD_REASSIGN_WITH_DEFAULT ] ) ;
4140
41+ /// The token for the Default -trait.
42+ const DEFAULT_TRAIT_TOKEN : & str = "Default" ;
43+ const DEFAULT_FUNC_TOKEN : & str = "default" ;
44+
4245impl EarlyLintPass for FieldReassignWithDefault {
4346 fn check_block ( & mut self , cx : & EarlyContext < ' _ > , block : & Block ) {
4447 // store statement index and name of binding for all statements like
@@ -49,17 +52,18 @@ impl EarlyLintPass for FieldReassignWithDefault {
4952 . enumerate ( )
5053 . filter_map ( |( idx, stmt) | {
5154 if_chain ! {
52- // only take `let ...`
55+ // only take `let ...` statements
5356 if let StmtKind :: Local ( ref local) = stmt. kind;
54- // only take `... mut < binding> ...`
57+ // only take `... mut binding ...`
5558 if let PatKind :: Ident ( BindingMode :: ByValue ( Mutability :: Mut ) , binding, _) = local. pat. kind;
5659 // only when assigning `... = Default::default()`
5760 if let Some ( ref expr) = local. init;
5861 if let ExprKind :: Call ( ref fn_expr, _) = & expr. kind;
59- if let ExprKind :: Path ( _, path) = & fn_expr. kind;
62+ if let ExprKind :: Path ( _, path ) = & fn_expr. kind;
6063 if path. segments. len( ) >= 2 ;
61- if path. segments[ path. segments. len( ) -2 ] . ident. as_str( ) == "Default" ;
62- if path. segments. last( ) . unwrap( ) . ident. as_str( ) == "default" ;
64+ // right hand side of assignment is `Default::default`
65+ if path. segments[ path. segments. len( ) -2 ] . ident. to_string( ) == DEFAULT_TRAIT_TOKEN ;
66+ if path. segments. last( ) . unwrap( ) . ident. to_string( ) == DEFAULT_FUNC_TOKEN ;
6367 then {
6468 Some ( ( idx, binding. name) )
6569 }
@@ -87,7 +91,7 @@ impl EarlyLintPass for FieldReassignWithDefault {
8791 if let ExprKind :: Assign ( ref later_lhs, ref later_rhs, _) = later_expr. kind;
8892 // only take assignments to fields where the field refers to the same binding as the previous statement
8993 if let ExprKind :: Field ( ref binding_name_candidate, later_field_ident) = later_lhs. kind;
90- if let ExprKind :: Path ( _, path) = & binding_name_candidate. kind;
94+ if let ExprKind :: Path ( _, ref path ) = binding_name_candidate. kind;
9195 if let Some ( second_binding_name) = path. segments. last( ) ;
9296 if second_binding_name. ident. name == binding_name;
9397 then {
@@ -96,17 +100,17 @@ impl EarlyLintPass for FieldReassignWithDefault {
96100 if let StmtKind :: Local ( preceding_local) = & stmt. kind {
97101 // reorganize the latter assigment statement into `field` and `value` for the lint
98102 let field = later_field_ident. name. as_str( ) ;
99- let value = expr_to_string ( later_rhs) ;
103+ let value_snippet = snippet ( cx , later_rhs. span , ".." ) ;
100104 if let Some ( ty) = & preceding_local. ty {
101- let ty = ty_to_string ( ty ) ;
105+ let ty_snippet = snippet ( cx , ty . span , "_" ) ;
102106
103107 span_lint_and_note(
104108 cx,
105109 FIELD_REASSIGN_WITH_DEFAULT ,
106110 later_stmt. span,
107111 "field assignment outside of initializer for an instance created with Default::default()" ,
108- preceding_local. span,
109- & format!( "consider initializing the variable immutably with `{} {{ {}: {}, ..Default::default() }}`" , ty , field, value ) ,
112+ Some ( preceding_local. span) ,
113+ & format!( "consider initializing the variable immutably with `{} {{ {}: {}, ..Default::default() }}`" , ty_snippet , field, value_snippet ) ,
110114 ) ;
111115 }
112116 }
0 commit comments