@@ -232,11 +232,14 @@ impl LateLintPass for LoopsPass {
232
232
}
233
233
}
234
234
if let ExprMatch ( ref expr, ref arms, MatchSource :: WhileLetDesugar ) = expr. node {
235
+ let body = & arms[ 0 ] . body ;
235
236
let pat = & arms[ 0 ] . pats [ 0 ] . node ;
236
- if let ( & PatEnum ( ref path, _) , & ExprMethodCall ( method_name, _, _) ) = ( pat, & expr. node ) {
237
+ if let ( & PatEnum ( ref path, _) , & ExprMethodCall ( method_name, _, ref args) ) = ( pat, & expr. node ) {
238
+ let iterator_def_id = var_def_id ( cx, & args[ 0 ] ) ;
237
239
if method_name. node . as_str ( ) == "next" &&
238
240
match_trait_method ( cx, expr, & [ "core" , "iter" , "Iterator" ] ) &&
239
- path. segments . last ( ) . unwrap ( ) . identifier . name . as_str ( ) == "Some" {
241
+ path. segments . last ( ) . unwrap ( ) . identifier . name . as_str ( ) == "Some" &&
242
+ !var_used ( body, iterator_def_id, cx) {
240
243
span_lint ( cx, WHILE_LET_ON_ITERATOR , expr. span ,
241
244
"this loop could be written as a `for` loop" ) ;
242
245
}
@@ -314,6 +317,32 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
314
317
}
315
318
}
316
319
320
+ fn var_used ( expr : & Expr , def_id : Option < NodeId > , cx : & LateContext ) -> bool {
321
+ match def_id {
322
+ None => false ,
323
+ Some ( def_id) => {
324
+ let mut visitor = VarUsedVisitor { def_id : def_id, found : false , cx : cx } ;
325
+ walk_expr ( & mut visitor, expr) ;
326
+ visitor. found
327
+ }
328
+ }
329
+ }
330
+
331
+ struct VarUsedVisitor < ' v , ' t : ' v > {
332
+ cx : & ' v LateContext < ' v , ' t > ,
333
+ def_id : NodeId ,
334
+ found : bool
335
+ }
336
+
337
+ impl < ' v , ' t > Visitor < ' v > for VarUsedVisitor < ' v , ' t > {
338
+ fn visit_expr ( & mut self , expr : & ' v Expr ) {
339
+ if Some ( self . def_id ) == var_def_id ( self . cx , expr) {
340
+ self . found = true ;
341
+ }
342
+ walk_expr ( self , expr) ;
343
+ }
344
+ }
345
+
317
346
/// Return true if the type of expr is one that provides IntoIterator impls
318
347
/// for &T and &mut T, such as Vec.
319
348
fn is_ref_iterable_type ( cx : & LateContext , e : & Expr ) -> bool {
0 commit comments