1
1
use clippy_utils:: ty:: { has_iter_method, implements_trait} ;
2
2
use clippy_utils:: { get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg} ;
3
3
use if_chain:: if_chain;
4
+ use rustc_ast:: ast:: { LitIntType , LitKind } ;
4
5
use rustc_errors:: Applicability ;
5
- use rustc_hir:: intravisit:: { walk_expr, walk_pat, walk_stmt, NestedVisitorMap , Visitor } ;
6
- use rustc_hir:: HirIdMap ;
7
- use rustc_hir:: { BinOpKind , BorrowKind , Expr , ExprKind , HirId , Mutability , Pat , PatKind , Stmt , StmtKind } ;
6
+ use rustc_hir:: intravisit:: { walk_expr, walk_local, walk_pat, walk_stmt, NestedVisitorMap , Visitor } ;
7
+ use rustc_hir:: { BinOpKind , BorrowKind , Expr , ExprKind , HirId , HirIdMap , Local , Mutability , Pat , PatKind , Stmt } ;
8
8
use rustc_lint:: LateContext ;
9
9
use rustc_middle:: hir:: map:: Map ;
10
+ use rustc_middle:: ty:: Ty ;
10
11
use rustc_span:: source_map:: Span ;
12
+ use rustc_span:: source_map:: Spanned ;
11
13
use rustc_span:: symbol:: { sym, Symbol } ;
14
+ use rustc_typeck:: hir_ty_to_ty;
12
15
use std:: iter:: Iterator ;
13
16
14
17
#[ derive( Debug , PartialEq ) ]
@@ -106,10 +109,11 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
106
109
}
107
110
108
111
enum InitializeVisitorState < ' hir > {
109
- Initial , // Not examined yet
110
- Declared ( Symbol ) , // Declared but not (yet) initialized
112
+ Initial , // Not examined yet
113
+ Declared ( Symbol , Option < Ty < ' hir > > ) , // Declared but not (yet) initialized
111
114
Initialized {
112
115
name : Symbol ,
116
+ ty : Option < Ty < ' hir > > ,
113
117
initializer : & ' hir Expr < ' hir > ,
114
118
} ,
115
119
DontWarn ,
@@ -138,9 +142,9 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
138
142
}
139
143
}
140
144
141
- pub ( super ) fn get_result ( & self ) -> Option < ( Symbol , & ' tcx Expr < ' tcx > ) > {
142
- if let InitializeVisitorState :: Initialized { name, initializer } = self . state {
143
- Some ( ( name, initializer) )
145
+ pub ( super ) fn get_result ( & self ) -> Option < ( Symbol , Option < Ty < ' tcx > > , & ' tcx Expr < ' tcx > ) > {
146
+ if let InitializeVisitorState :: Initialized { name, ty , initializer } = self . state {
147
+ Some ( ( name, ty , initializer) )
144
148
} else {
145
149
None
146
150
}
@@ -150,22 +154,25 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
150
154
impl < ' a , ' tcx > Visitor < ' tcx > for InitializeVisitor < ' a , ' tcx > {
151
155
type Map = Map < ' tcx > ;
152
156
153
- fn visit_stmt ( & mut self , stmt : & ' tcx Stmt < ' _ > ) {
157
+ fn visit_local ( & mut self , l : & ' tcx Local < ' _ > ) {
154
158
// Look for declarations of the variable
155
159
if_chain ! {
156
- if let StmtKind :: Local ( local) = stmt. kind;
157
- if local. pat. hir_id == self . var_id;
158
- if let PatKind :: Binding ( .., ident, _) = local. pat. kind;
160
+ if l. pat. hir_id == self . var_id;
161
+ if let PatKind :: Binding ( .., ident, _) = l. pat. kind;
159
162
then {
160
- self . state = local. init. map_or( InitializeVisitorState :: Declared ( ident. name) , |init| {
163
+ let ty = l. ty. map( |ty| hir_ty_to_ty( self . cx. tcx, ty) ) ;
164
+
165
+ self . state = l. init. map_or( InitializeVisitorState :: Declared ( ident. name, ty) , |init| {
161
166
InitializeVisitorState :: Initialized {
162
167
initializer: init,
168
+ ty,
163
169
name: ident. name,
164
170
}
165
171
} )
166
172
}
167
173
}
168
- walk_stmt ( self , stmt) ;
174
+
175
+ walk_local ( self , l) ;
169
176
}
170
177
171
178
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
@@ -195,15 +202,38 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
195
202
self . state = InitializeVisitorState :: DontWarn ;
196
203
} ,
197
204
ExprKind :: Assign ( lhs, rhs, _) if lhs. hir_id == expr. hir_id => {
198
- self . state = if_chain ! {
199
- if self . depth == 0 ;
200
- if let InitializeVisitorState :: Declared ( name)
201
- | InitializeVisitorState :: Initialized { name, ..} = self . state;
202
- then {
203
- InitializeVisitorState :: Initialized { initializer: rhs, name }
204
- } else {
205
- InitializeVisitorState :: DontWarn
205
+ self . state = if self . depth == 0 {
206
+ match self . state {
207
+ InitializeVisitorState :: Declared ( name, mut ty) => {
208
+ if ty. is_none ( ) {
209
+ if let ExprKind :: Lit ( Spanned {
210
+ node : LitKind :: Int ( _, LitIntType :: Unsuffixed ) ,
211
+ ..
212
+ } ) = rhs. kind
213
+ {
214
+ ty = None ;
215
+ } else {
216
+ ty = self . cx . typeck_results ( ) . expr_ty_opt ( rhs) ;
217
+ }
218
+ }
219
+
220
+ InitializeVisitorState :: Initialized {
221
+ initializer : rhs,
222
+ ty,
223
+ name,
224
+ }
225
+ } ,
226
+ InitializeVisitorState :: Initialized { ty, name, .. } => {
227
+ InitializeVisitorState :: Initialized {
228
+ initializer : rhs,
229
+ ty,
230
+ name,
231
+ }
232
+ } ,
233
+ _ => InitializeVisitorState :: DontWarn ,
206
234
}
235
+ } else {
236
+ InitializeVisitorState :: DontWarn
207
237
}
208
238
} ,
209
239
ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) if mutability == Mutability :: Mut => {
0 commit comments