@@ -11,7 +11,8 @@ use std::collections::{HashSet,HashMap};
11
11
use syntax:: ast:: Lit_ :: * ;
12
12
13
13
use utils:: { snippet, span_lint, get_parent_expr, match_trait_method, match_type,
14
- in_external_macro, expr_block, span_help_and_lint, is_integer_literal} ;
14
+ in_external_macro, expr_block, span_help_and_lint, is_integer_literal,
15
+ get_enclosing_block} ;
15
16
use utils:: { VEC_PATH , LL_PATH } ;
16
17
17
18
declare_lint ! { pub NEEDLESS_RANGE_LOOP , Warn ,
@@ -232,17 +233,16 @@ impl LateLintPass for LoopsPass {
232
233
}
233
234
}
234
235
if let ExprMatch ( ref match_expr, ref arms, MatchSource :: WhileLetDesugar ) = expr. node {
235
- let body = & arms[ 0 ] . body ;
236
236
let pat = & arms[ 0 ] . pats [ 0 ] . node ;
237
237
if let ( & PatEnum ( ref path, Some ( ref pat_args) ) ,
238
238
& ExprMethodCall ( method_name, _, ref method_args) ) =
239
239
( pat, & match_expr. node ) {
240
- let iterator_def_id = var_def_id ( cx , & method_args[ 0 ] ) ;
240
+ let iter_expr = & method_args[ 0 ] ;
241
241
if let Some ( lhs_constructor) = path. segments . last ( ) {
242
242
if method_name. node . as_str ( ) == "next" &&
243
243
match_trait_method ( cx, match_expr, & [ "core" , "iter" , "Iterator" ] ) &&
244
244
lhs_constructor. identifier . name . as_str ( ) == "Some" &&
245
- !var_used ( body , iterator_def_id , cx ) {
245
+ !is_iterator_used_after_while_let ( cx , iter_expr ) {
246
246
let iterator = snippet ( cx, method_args[ 0 ] . span , "_" ) ;
247
247
let loop_var = snippet ( cx, pat_args[ 0 ] . span , "_" ) ;
248
248
span_help_and_lint ( cx, WHILE_LET_ON_ITERATOR , expr. span ,
@@ -326,32 +326,46 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
326
326
}
327
327
}
328
328
329
- fn var_used ( expr : & Expr , def_id : Option < NodeId > , cx : & LateContext ) -> bool {
330
- match def_id {
331
- None => false ,
332
- Some ( def_id) => {
333
- let mut visitor = VarUsedVisitor { def_id : def_id, found : false , cx : cx } ;
334
- walk_expr ( & mut visitor, expr) ;
335
- visitor. found
336
- }
329
+ fn is_iterator_used_after_while_let ( cx : & LateContext , iter_expr : & Expr ) -> bool {
330
+ let def_id = match var_def_id ( cx, iter_expr) {
331
+ Some ( id) => id,
332
+ None => return false
333
+ } ;
334
+ let mut visitor = VarUsedAfterLoopVisitor {
335
+ cx : cx,
336
+ def_id : def_id,
337
+ iter_expr_id : iter_expr. id ,
338
+ past_while_let : false ,
339
+ var_used_after_while_let : false
340
+ } ;
341
+ if let Some ( enclosing_block) = get_enclosing_block ( cx, def_id) {
342
+ walk_block ( & mut visitor, enclosing_block) ;
337
343
}
344
+ visitor. var_used_after_while_let
338
345
}
339
346
340
- struct VarUsedVisitor < ' v , ' t : ' v > {
347
+ struct VarUsedAfterLoopVisitor < ' v , ' t : ' v > {
341
348
cx : & ' v LateContext < ' v , ' t > ,
342
349
def_id : NodeId ,
343
- found : bool
350
+ iter_expr_id : NodeId ,
351
+ past_while_let : bool ,
352
+ var_used_after_while_let : bool
344
353
}
345
354
346
- impl < ' v , ' t > Visitor < ' v > for VarUsedVisitor < ' v , ' t > {
355
+ impl < ' v , ' t > Visitor < ' v > for VarUsedAfterLoopVisitor < ' v , ' t > {
347
356
fn visit_expr ( & mut self , expr : & ' v Expr ) {
348
- if Some ( self . def_id ) == var_def_id ( self . cx , expr) {
349
- self . found = true ;
357
+ if self . past_while_let {
358
+ if Some ( self . def_id ) == var_def_id ( self . cx , expr) {
359
+ self . var_used_after_while_let = true ;
360
+ }
361
+ } else if self . iter_expr_id == expr. id {
362
+ self . past_while_let = true ;
350
363
}
351
364
walk_expr ( self , expr) ;
352
365
}
353
366
}
354
367
368
+
355
369
/// Return true if the type of expr is one that provides IntoIterator impls
356
370
/// for &T and &mut T, such as Vec.
357
371
fn is_ref_iterable_type ( cx : & LateContext , e : & Expr ) -> bool {
0 commit comments