@@ -3,7 +3,7 @@ use if_chain::if_chain;
3
3
use rustc_data_structures:: fx:: FxHashMap ;
4
4
use rustc_hir:: def:: Res ;
5
5
use rustc_hir:: { Block , Expr , ExprKind , PatKind , QPath , Stmt , StmtKind } ;
6
- use rustc_middle:: ty:: { self , Adt , TyS } ;
6
+ use rustc_middle:: ty:: { self , Adt , Ty } ;
7
7
use rustc_span:: symbol:: { Ident , Symbol } ;
8
8
9
9
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -44,7 +44,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
44
44
// find all binding statements like `let mut _ = T::default()` where `T::default()` is the
45
45
// `default` method of the `Default` trait, and store statement index in current block being
46
46
// checked and the name of the bound variable
47
- let binding_statements_using_default: Vec < ( usize , Symbol , & TyS < ' _ > ) > =
47
+ let binding_statements_using_default =
48
48
enumerate_bindings_using_default ( cx, block) ;
49
49
50
50
// start from the `let mut _ = _::default();` and look at all the following
@@ -94,7 +94,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
94
94
95
95
if let StmtKind :: Local ( preceding_local) = & stmt. kind {
96
96
// if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
97
- let ext_with_default = !fields_of_type ( & binding_type)
97
+ let ext_with_default = !fields_of_type ( binding_type)
98
98
. iter ( )
99
99
. all ( |field| assigned_fields. contains_key ( & field. name ) ) ;
100
100
@@ -114,7 +114,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
114
114
span_lint_and_note (
115
115
cx,
116
116
FIELD_REASSIGN_WITH_DEFAULT ,
117
- first_assign. unwrap_or_else ( || unreachable ! ( ) ) . span ,
117
+ first_assign. unwrap ( ) . span ,
118
118
"field assignment outside of initializer for an instance created with Default::default()" ,
119
119
Some ( preceding_local. span ) ,
120
120
& format ! ( "consider initializing the variable with `{}`" , sugg) ,
@@ -127,10 +127,7 @@ impl LateLintPass<'_> for FieldReassignWithDefault {
127
127
128
128
/// Returns the block indices, identifiers and types of bindings set as `Default::default()`, except
129
129
/// for when the pattern type is a tuple.
130
- fn enumerate_bindings_using_default < ' cx , ' hir > (
131
- cx : & LateContext < ' cx > ,
132
- block : & Block < ' hir > ,
133
- ) -> Vec < ( usize , Symbol , & ' cx TyS < ' cx > ) > {
130
+ fn enumerate_bindings_using_default < ' tcx > ( cx : & LateContext < ' tcx > , block : & Block < ' _ > ) -> Vec < ( usize , Symbol , Ty < ' tcx > ) > {
134
131
block
135
132
. stmts
136
133
. iter ( )
@@ -141,6 +138,9 @@ fn enumerate_bindings_using_default<'cx, 'hir>(
141
138
if let StmtKind :: Local ( ref local) = stmt. kind;
142
139
// only take bindings to identifiers
143
140
if let PatKind :: Binding ( _, _, ident, _) = local. pat. kind;
141
+ // that are not tuples
142
+ let ty = cx. typeck_results( ) . pat_ty( local. pat) ;
143
+ if !matches!( ty. kind( ) , ty:: Tuple ( _) ) ;
144
144
// only when assigning `... = Default::default()`
145
145
if let Some ( ref expr) = local. init;
146
146
if let ExprKind :: Call ( ref fn_expr, _) = & expr. kind;
@@ -149,12 +149,6 @@ fn enumerate_bindings_using_default<'cx, 'hir>(
149
149
// right hand side of assignment is `Default::default`
150
150
if match_def_path( cx, def_id, & paths:: DEFAULT_TRAIT_METHOD ) ;
151
151
then {
152
- // Get the type of the pattern
153
- let ty = cx. typeck_results( ) . pat_ty( local. pat) ;
154
- // Ignore tuples
155
- if let ty:: Tuple ( _) = ty. kind( ) {
156
- return None ;
157
- }
158
152
Some ( ( idx, ident. name, ty) )
159
153
} else {
160
154
None
@@ -174,7 +168,7 @@ fn stmt_shadows_binding(this: &Stmt<'_>, shadowed: Symbol) -> bool {
174
168
}
175
169
176
170
/// Returns the reassigned field and the assigning expression (right-hand side of assign).
177
- fn field_reassigned_by_stmt < ' hir > ( this : & Stmt < ' hir > , binding_name : Symbol ) -> Option < ( Ident , & ' hir Expr < ' hir > ) > {
171
+ fn field_reassigned_by_stmt < ' tcx > ( this : & Stmt < ' tcx > , binding_name : Symbol ) -> Option < ( Ident , & ' tcx Expr < ' tcx > ) > {
178
172
if_chain ! {
179
173
// only take assignments
180
174
if let StmtKind :: Semi ( ref later_expr) = this. kind;
@@ -195,11 +189,11 @@ fn field_reassigned_by_stmt<'hir>(this: &Stmt<'hir>, binding_name: Symbol) -> Op
195
189
}
196
190
197
191
/// Returns the vec of fields for a struct and an empty vec for non-struct ADTs.
198
- fn fields_of_type < ' a > ( ty : & ' a TyS < ' _ > ) -> Vec < Ident > {
192
+ fn fields_of_type ( ty : Ty < ' _ > ) -> Vec < Ident > {
199
193
if let Adt ( adt, _) = ty. kind ( ) {
200
194
if adt. is_struct ( ) {
201
195
// unwrap is safe, because this is a struct and structs have only one variant
202
- let variant = & adt. variants . get ( 0_usize . into ( ) ) . unwrap ( ) ;
196
+ let variant = & adt. non_enum_variant ( ) ;
203
197
return variant. fields . iter ( ) . map ( |f| f. ident ) . collect ( ) ;
204
198
}
205
199
}
0 commit comments