@@ -12,8 +12,10 @@ use std::borrow::Cow;
1212use std:: collections:: HashMap ;
1313
1414use utils:: { snippet, span_lint, get_parent_expr, match_trait_method, match_type, in_external_macro,
15- span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then, walk_ptrs_ty} ;
15+ span_help_and_lint, is_integer_literal, get_enclosing_block, span_lint_and_then,
16+ unsugar_range, walk_ptrs_ty} ;
1617use utils:: { BTREEMAP_PATH , HASHMAP_PATH , LL_PATH , OPTION_PATH , RESULT_PATH , VEC_PATH } ;
18+ use utils:: UnsugaredRange ;
1719
1820/// **What it does:** This lint checks for looping over the range of `0..len` of some collection just to get the values by index.
1921///
@@ -323,10 +325,9 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E
323325/// Check for looping over a range and then indexing a sequence with it.
324326/// The iteratee must be a range literal.
325327fn check_for_loop_range ( cx : & LateContext , pat : & Pat , arg : & Expr , body : & Expr , expr : & Expr ) {
326- if let ExprRange ( Some ( ref l ) , ref r ) = arg. node {
328+ if let Some ( UnsugaredRange { start : Some ( ref start ) , ref end , .. } ) = unsugar_range ( & arg) {
327329 // the var must be a single name
328330 if let PatKind :: Ident ( _, ref ident, _) = pat. node {
329-
330331 let mut visitor = VarVisitor {
331332 cx : cx,
332333 var : ident. node . name ,
@@ -348,19 +349,19 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
348349 return ;
349350 }
350351
351- let starts_at_zero = is_integer_literal ( l , 0 ) ;
352+ let starts_at_zero = is_integer_literal ( start , 0 ) ;
352353
353354 let skip: Cow < _ > = if starts_at_zero {
354355 "" . into ( )
355356 } else {
356- format ! ( ".skip({})" , snippet( cx, l . span, ".." ) ) . into ( )
357+ format ! ( ".skip({})" , snippet( cx, start . span, ".." ) ) . into ( )
357358 } ;
358359
359- let take: Cow < _ > = if let Some ( ref r ) = * r {
360- if is_len_call ( & r , & indexed) {
360+ let take: Cow < _ > = if let Some ( ref end ) = * end {
361+ if is_len_call ( & end , & indexed) {
361362 "" . into ( )
362363 } else {
363- format ! ( ".take({})" , snippet( cx, r . span, ".." ) ) . into ( )
364+ format ! ( ".take({})" , snippet( cx, end . span, ".." ) ) . into ( )
364365 }
365366 } else {
366367 "" . into ( )
@@ -416,27 +417,27 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool {
416417
417418fn check_for_loop_reverse_range ( cx : & LateContext , arg : & Expr , expr : & Expr ) {
418419 // if this for loop is iterating over a two-sided range...
419- if let ExprRange ( Some ( ref start_expr ) , Some ( ref stop_expr ) ) = arg. node {
420+ if let Some ( UnsugaredRange { start : Some ( ref start ) , end : Some ( ref end ) , .. } ) = unsugar_range ( & arg) {
420421 // ...and both sides are compile-time constant integers...
421- if let Ok ( start_idx) = eval_const_expr_partial ( & cx. tcx , start_expr , ExprTypeChecked , None ) {
422- if let Ok ( stop_idx ) = eval_const_expr_partial ( & cx. tcx , stop_expr , ExprTypeChecked , None ) {
423- // ...and the start index is greater than the stop index,
422+ if let Ok ( start_idx) = eval_const_expr_partial ( & cx. tcx , start , ExprTypeChecked , None ) {
423+ if let Ok ( end_idx ) = eval_const_expr_partial ( & cx. tcx , end , ExprTypeChecked , None ) {
424+ // ...and the start index is greater than the end index,
424425 // this loop will never run. This is often confusing for developers
425426 // who think that this will iterate from the larger value to the
426427 // smaller value.
427- let ( sup, eq) = match ( start_idx, stop_idx ) {
428- ( ConstVal :: Int ( start_idx) , ConstVal :: Int ( stop_idx ) ) => {
429- ( start_idx > stop_idx , start_idx == stop_idx )
428+ let ( sup, eq) = match ( start_idx, end_idx ) {
429+ ( ConstVal :: Int ( start_idx) , ConstVal :: Int ( end_idx ) ) => {
430+ ( start_idx > end_idx , start_idx == end_idx )
430431 }
431- ( ConstVal :: Uint ( start_idx) , ConstVal :: Uint ( stop_idx ) ) => {
432- ( start_idx > stop_idx , start_idx == stop_idx )
432+ ( ConstVal :: Uint ( start_idx) , ConstVal :: Uint ( end_idx ) ) => {
433+ ( start_idx > end_idx , start_idx == end_idx )
433434 }
434435 _ => ( false , false ) ,
435436 } ;
436437
437438 if sup {
438- let start_snippet = snippet ( cx, start_expr . span , "_" ) ;
439- let stop_snippet = snippet ( cx, stop_expr . span , "_" ) ;
439+ let start_snippet = snippet ( cx, start . span , "_" ) ;
440+ let end_snippet = snippet ( cx, end . span , "_" ) ;
440441
441442 span_lint_and_then ( cx,
442443 REVERSE_RANGE_LOOP ,
@@ -447,7 +448,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) {
447448 "consider using the following if \
448449 you are attempting to iterate \
449450 over this range in reverse",
450- format ! ( "({}..{}).rev()` " , stop_snippet , start_snippet) ) ;
451+ format ! ( "({}..{}).rev()` " , end_snippet , start_snippet) ) ;
451452 } ) ;
452453 } else if eq {
453454 // if they are equal, it's also problematic - this loop
0 commit comments