11use clippy_utils:: ty:: { has_iter_method, implements_trait} ;
22use clippy_utils:: { get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg} ;
33use if_chain:: if_chain;
4+ use rustc_ast:: ast:: { LitIntType , LitKind } ;
45use 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 } ;
88use rustc_lint:: LateContext ;
99use rustc_middle:: hir:: map:: Map ;
10+ use rustc_middle:: ty:: Ty ;
1011use rustc_span:: source_map:: Span ;
12+ use rustc_span:: source_map:: Spanned ;
1113use rustc_span:: symbol:: { sym, Symbol } ;
14+ use rustc_typeck:: hir_ty_to_ty;
1215use std:: iter:: Iterator ;
1316
1417#[ derive( Debug , PartialEq ) ]
@@ -106,10 +109,11 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
106109}
107110
108111enum 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
111114 Initialized {
112115 name : Symbol ,
116+ ty : Option < Ty < ' hir > > ,
113117 initializer : & ' hir Expr < ' hir > ,
114118 } ,
115119 DontWarn ,
@@ -138,9 +142,9 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
138142 }
139143 }
140144
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) )
144148 } else {
145149 None
146150 }
@@ -150,22 +154,25 @@ impl<'a, 'tcx> InitializeVisitor<'a, 'tcx> {
150154impl < ' a , ' tcx > Visitor < ' tcx > for InitializeVisitor < ' a , ' tcx > {
151155 type Map = Map < ' tcx > ;
152156
153- fn visit_stmt ( & mut self , stmt : & ' tcx Stmt < ' _ > ) {
157+ fn visit_local ( & mut self , l : & ' tcx Local < ' _ > ) {
154158 // Look for declarations of the variable
155159 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;
159162 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| {
161166 InitializeVisitorState :: Initialized {
162167 initializer: init,
168+ ty,
163169 name: ident. name,
164170 }
165171 } )
166172 }
167173 }
168- walk_stmt ( self , stmt) ;
174+
175+ walk_local ( self , l) ;
169176 }
170177
171178 fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
@@ -195,15 +202,38 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
195202 self . state = InitializeVisitorState :: DontWarn ;
196203 } ,
197204 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 ,
206234 }
235+ } else {
236+ InitializeVisitorState :: DontWarn
207237 }
208238 } ,
209239 ExprKind :: AddrOf ( BorrowKind :: Ref , mutability, _) if mutability == Mutability :: Mut => {
0 commit comments