@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
8
8
use rustc_hir:: def:: { DefKind , Res } ;
9
9
use rustc_hir:: def_id:: DefId ;
10
10
use rustc_hir:: definitions:: { DefPathData , DisambiguatedDefPathData } ;
11
- use rustc_hir:: intravisit:: { walk_expr, FnKind , Visitor } ;
11
+ use rustc_hir:: intravisit:: { walk_expr, walk_stmt , FnKind , Visitor } ;
12
12
use rustc_hir:: {
13
13
Arm , Block , Body , Expr , ExprKind , Guard , HirId , ImplicitSelfKind , Let , Local , Pat , PatKind , Path , PathSegment ,
14
14
QPath , Stmt , StmtKind , TyKind , UnOp ,
@@ -145,7 +145,8 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
145
145
is_method : matches ! ( kind, FnKind :: Method ( ..) ) ,
146
146
has_self,
147
147
ty_res,
148
- ty_ctx : cx. tcx ,
148
+ tcx : cx. tcx ,
149
+ visited_exprs : FxHashSet :: default ( ) ,
149
150
} ;
150
151
151
152
visitor. visit_expr ( & body. value ) ;
@@ -206,19 +207,13 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
206
207
}
207
208
208
209
pub fn is_primitive ( ty : Ty < ' _ > ) -> bool {
209
- match ty. kind ( ) {
210
- ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Str => true ,
211
- ty:: Ref ( _, t, _) => is_primitive ( * t) ,
212
- _ => false ,
213
- }
210
+ let ty = ty. peel_refs ( ) ;
211
+ ty. is_primitive ( ) || ty. is_str ( )
214
212
}
215
213
216
214
pub fn is_array ( ty : Ty < ' _ > ) -> bool {
217
- match ty. kind ( ) {
218
- ty:: Array ( ..) | ty:: Slice ( ..) => true ,
219
- ty:: Ref ( _, t, _) => is_array ( * t) ,
220
- _ => false ,
221
- }
215
+ let ty = ty. peel_refs ( ) ;
216
+ ty. is_array ( ) || ty. is_array_slice ( )
222
217
}
223
218
224
219
/// This builds the graph of side effect.
@@ -250,40 +245,30 @@ pub struct SideEffectVisit<'tcx> {
250
245
is_method : bool ,
251
246
has_self : bool ,
252
247
ty_res : & ' tcx TypeckResults < ' tcx > ,
253
- ty_ctx : TyCtxt < ' tcx > ,
248
+ tcx : TyCtxt < ' tcx > ,
249
+ visited_exprs : FxHashSet < HirId > ,
254
250
}
255
251
256
252
impl < ' tcx > Visitor < ' tcx > for SideEffectVisit < ' tcx > {
257
- fn visit_block ( & mut self , b : & ' tcx Block < ' tcx > ) {
258
- b. stmts . iter ( ) . for_each ( |stmt| {
259
- self . visit_stmt ( stmt) ;
260
- self . ret_vars . clear ( ) ;
261
- } ) ;
262
- walk_list ! ( self , visit_expr, b. expr) ;
263
- }
264
-
265
253
fn visit_stmt ( & mut self , s : & ' tcx Stmt < ' tcx > ) {
266
254
match s. kind {
267
255
StmtKind :: Local ( Local {
268
256
pat, init : Some ( init) , ..
269
257
} ) => {
270
258
self . visit_pat_expr ( pat, init, false ) ;
271
- self . ret_vars . clear ( ) ;
272
259
} ,
273
- StmtKind :: Item ( i) => {
274
- let item = self . ty_ctx . hir ( ) . item ( i) ;
275
- self . visit_item ( item) ;
276
- self . ret_vars . clear ( ) ;
277
- } ,
278
- StmtKind :: Expr ( e) | StmtKind :: Semi ( e) => {
279
- self . visit_expr ( e) ;
280
- self . ret_vars . clear ( ) ;
260
+ StmtKind :: Item ( _) | StmtKind :: Expr ( _) | StmtKind :: Semi ( _) => {
261
+ walk_stmt ( self , s) ;
281
262
} ,
282
263
StmtKind :: Local ( _) => { } ,
283
264
}
265
+ self . ret_vars . clear ( ) ;
284
266
}
285
267
286
268
fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
269
+ if !self . visited_exprs . insert ( ex. hir_id ) {
270
+ return ;
271
+ }
287
272
match ex. kind {
288
273
ExprKind :: Array ( exprs) | ExprKind :: Tup ( exprs) => {
289
274
self . ret_vars = exprs
@@ -307,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for SideEffectVisit<'tcx> {
307
292
ExprKind :: Match ( expr, arms, _) => self . visit_match ( expr, arms) ,
308
293
// since analysing the closure is not easy, just set all variables in it to side-effect
309
294
ExprKind :: Closure ( _, _, body_id, _, _) => {
310
- let body = self . ty_ctx . hir ( ) . body ( body_id) ;
295
+ let body = self . tcx . hir ( ) . body ( body_id) ;
311
296
self . visit_body ( body) ;
312
297
let vars = std:: mem:: take ( & mut self . ret_vars ) ;
313
298
self . add_side_effect ( vars) ;
0 commit comments