@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
88use rustc_hir:: def:: { DefKind , Res } ;
99use rustc_hir:: def_id:: DefId ;
1010use 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 } ;
1212use rustc_hir:: {
1313 Arm , Block , Body , Expr , ExprKind , Guard , HirId , ImplicitSelfKind , Let , Local , Pat , PatKind , Path , PathSegment ,
1414 QPath , Stmt , StmtKind , TyKind , UnOp ,
@@ -145,7 +145,8 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
145145 is_method : matches ! ( kind, FnKind :: Method ( ..) ) ,
146146 has_self,
147147 ty_res,
148- ty_ctx : cx. tcx ,
148+ tcx : cx. tcx ,
149+ visited_exprs : FxHashSet :: default ( ) ,
149150 } ;
150151
151152 visitor. visit_expr ( & body. value ) ;
@@ -206,19 +207,13 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
206207}
207208
208209pub 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 ( )
214212}
215213
216214pub 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 ( )
222217}
223218
224219/// This builds the graph of side effect.
@@ -250,40 +245,30 @@ pub struct SideEffectVisit<'tcx> {
250245 is_method : bool ,
251246 has_self : bool ,
252247 ty_res : & ' tcx TypeckResults < ' tcx > ,
253- ty_ctx : TyCtxt < ' tcx > ,
248+ tcx : TyCtxt < ' tcx > ,
249+ visited_exprs : FxHashSet < HirId > ,
254250}
255251
256252impl < ' 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-
265253 fn visit_stmt ( & mut self , s : & ' tcx Stmt < ' tcx > ) {
266254 match s. kind {
267255 StmtKind :: Local ( Local {
268256 pat, init : Some ( init) , ..
269257 } ) => {
270258 self . visit_pat_expr ( pat, init, false ) ;
271- self . ret_vars . clear ( ) ;
272259 } ,
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) ;
281262 } ,
282263 StmtKind :: Local ( _) => { } ,
283264 }
265+ self . ret_vars . clear ( ) ;
284266 }
285267
286268 fn visit_expr ( & mut self , ex : & ' tcx Expr < ' tcx > ) {
269+ if !self . visited_exprs . insert ( ex. hir_id ) {
270+ return ;
271+ }
287272 match ex. kind {
288273 ExprKind :: Array ( exprs) | ExprKind :: Tup ( exprs) => {
289274 self . ret_vars = exprs
@@ -307,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for SideEffectVisit<'tcx> {
307292 ExprKind :: Match ( expr, arms, _) => self . visit_match ( expr, arms) ,
308293 // since analysing the closure is not easy, just set all variables in it to side-effect
309294 ExprKind :: Closure ( _, _, body_id, _, _) => {
310- let body = self . ty_ctx . hir ( ) . body ( body_id) ;
295+ let body = self . tcx . hir ( ) . body ( body_id) ;
311296 self . visit_body ( body) ;
312297 let vars = std:: mem:: take ( & mut self . ret_vars ) ;
313298 self . add_side_effect ( vars) ;
0 commit comments