1
1
use crate :: utils:: { contains_name, match_def_path, paths, qpath_res, snippet, span_lint_and_note} ;
2
2
use if_chain:: if_chain;
3
- use rustc_data_structures:: fx:: FxHashMap ;
4
3
use rustc_hir:: def:: Res ;
5
4
use rustc_hir:: { Block , Expr , ExprKind , PatKind , QPath , Stmt , StmtKind } ;
6
5
use rustc_middle:: ty:: { self , Adt , Ty } ;
@@ -57,7 +56,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
57
56
// find all "later statement"'s where the fields of the binding set as
58
57
// Default::default() get reassigned, unless the reassignment refers to the original binding
59
58
let mut first_assign = None ;
60
- let mut assigned_fields = FxHashMap :: default ( ) ;
59
+ let mut assigned_fields = Vec :: new ( ) ;
61
60
let mut cancel_lint = false ;
62
61
for consecutive_statement in & block. stmts [ stmt_idx + 1 ..] {
63
62
// interrupt if the statement is a let binding (`Local`) that shadows the original
@@ -75,8 +74,15 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
75
74
break ;
76
75
}
77
76
78
- // always re-insert set value, this way the latest value is stored for output snippet
79
- assigned_fields. insert ( field_ident. name , assign_rhs) ;
77
+ // if the field was previously assigned, replace the assignment, otherwise insert the assignment
78
+ if let Some ( prev) = assigned_fields
79
+ . iter_mut ( )
80
+ . find ( |( field_name, _) | field_name == & field_ident. name )
81
+ {
82
+ * prev = ( field_ident. name , assign_rhs) ;
83
+ } else {
84
+ assigned_fields. push ( ( field_ident. name , assign_rhs) ) ;
85
+ }
80
86
81
87
// also set first instance of error for help message
82
88
if first_assign. is_none ( ) {
@@ -100,12 +106,12 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
100
106
let assigned_fields = assigned_fields
101
107
. into_iter ( )
102
108
. filter ( |( _, rhs) | !is_expr_default ( rhs, cx) )
103
- . collect :: < FxHashMap < Symbol , & Expr < ' _ > > > ( ) ;
109
+ . collect :: < Vec < ( Symbol , & Expr < ' _ > ) > > ( ) ;
104
110
105
111
// if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
106
112
let ext_with_default = !fields_of_type ( binding_type)
107
113
. iter ( )
108
- . all ( |field| assigned_fields. contains_key ( & field. name ) ) ;
114
+ . all ( |field| assigned_fields. iter ( ) . any ( | ( a , _ ) | a == & field. name ) ) ;
109
115
110
116
let field_list = assigned_fields
111
117
. into_iter ( )
0 commit comments