@@ -11,7 +11,8 @@ use std::collections::{HashSet,HashMap};
1111use syntax:: ast:: Lit_ :: * ;
1212
1313use 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} ;
1516use utils:: { VEC_PATH , LL_PATH } ;
1617
1718declare_lint ! { pub NEEDLESS_RANGE_LOOP , Warn ,
@@ -232,17 +233,16 @@ impl LateLintPass for LoopsPass {
232233 }
233234 }
234235 if let ExprMatch ( ref match_expr, ref arms, MatchSource :: WhileLetDesugar ) = expr. node {
235- let body = & arms[ 0 ] . body ;
236236 let pat = & arms[ 0 ] . pats [ 0 ] . node ;
237237 if let ( & PatEnum ( ref path, Some ( ref pat_args) ) ,
238238 & ExprMethodCall ( method_name, _, ref method_args) ) =
239239 ( pat, & match_expr. node ) {
240- let iterator_def_id = var_def_id ( cx , & method_args[ 0 ] ) ;
240+ let iter_expr = & method_args[ 0 ] ;
241241 if let Some ( lhs_constructor) = path. segments . last ( ) {
242242 if method_name. node . as_str ( ) == "next" &&
243243 match_trait_method ( cx, match_expr, & [ "core" , "iter" , "Iterator" ] ) &&
244244 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 ) {
246246 let iterator = snippet ( cx, method_args[ 0 ] . span , "_" ) ;
247247 let loop_var = snippet ( cx, pat_args[ 0 ] . span , "_" ) ;
248248 span_help_and_lint ( cx, WHILE_LET_ON_ITERATOR , expr. span ,
@@ -326,32 +326,46 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
326326 }
327327}
328328
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) ;
337343 }
344+ visitor. var_used_after_while_let
338345}
339346
340- struct VarUsedVisitor < ' v , ' t : ' v > {
347+ struct VarUsedAfterLoopVisitor < ' v , ' t : ' v > {
341348 cx : & ' v LateContext < ' v , ' t > ,
342349 def_id : NodeId ,
343- found : bool
350+ iter_expr_id : NodeId ,
351+ past_while_let : bool ,
352+ var_used_after_while_let : bool
344353}
345354
346- impl < ' v , ' t > Visitor < ' v > for VarUsedVisitor < ' v , ' t > {
355+ impl < ' v , ' t > Visitor < ' v > for VarUsedAfterLoopVisitor < ' v , ' t > {
347356 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 ;
350363 }
351364 walk_expr ( self , expr) ;
352365 }
353366}
354367
368+
355369/// Return true if the type of expr is one that provides IntoIterator impls
356370/// for &T and &mut T, such as Vec.
357371fn is_ref_iterable_type ( cx : & LateContext , e : & Expr ) -> bool {
0 commit comments