@@ -27,9 +27,10 @@ use syntax_pos::{BytePos, Symbol};
27
27
28
28
use crate :: utils:: paths;
29
29
use crate :: utils:: {
30
- get_enclosing_block, get_parent_expr, has_iter_method, higher, is_integer_const, is_refutable, last_path_segment,
31
- match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt, snippet_with_applicability,
32
- span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, SpanlessEq ,
30
+ get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
31
+ is_integer_const, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg,
32
+ snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg,
33
+ span_lint_and_then, SpanlessEq ,
33
34
} ;
34
35
35
36
declare_clippy_lint ! {
@@ -1470,17 +1471,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>(
1470
1471
"for ({}, {}) in {}.enumerate()" ,
1471
1472
name,
1472
1473
snippet_with_applicability( cx, pat. span, "item" , & mut applicability) ,
1473
- if higher:: range( cx, arg) . is_some( ) {
1474
- format!(
1475
- "({})" ,
1476
- snippet_with_applicability( cx, arg. span, "_" , & mut applicability)
1477
- )
1478
- } else {
1479
- format!(
1480
- "{}" ,
1481
- sugg:: Sugg :: hir_with_applicability( cx, arg, "_" , & mut applicability) . maybe_par( )
1482
- )
1483
- }
1474
+ make_iterator_snippet( cx, arg, & mut applicability) ,
1484
1475
) ,
1485
1476
applicability,
1486
1477
) ;
@@ -1490,6 +1481,39 @@ fn check_for_loop_explicit_counter<'a, 'tcx>(
1490
1481
}
1491
1482
}
1492
1483
1484
+ /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
1485
+ /// actual `Iterator` that the loop uses.
1486
+ fn make_iterator_snippet ( cx : & LateContext < ' _ , ' _ > , arg : & Expr , applic_ref : & mut Applicability ) -> String {
1487
+ let impls_iterator = get_trait_def_id ( cx, & paths:: ITERATOR )
1488
+ . map_or ( false , |id| implements_trait ( cx, cx. tables . expr_ty ( arg) , id, & [ ] ) ) ;
1489
+ if impls_iterator {
1490
+ format ! (
1491
+ "{}" ,
1492
+ sugg:: Sugg :: hir_with_applicability( cx, arg, "_" , applic_ref) . maybe_par( )
1493
+ )
1494
+ } else {
1495
+ // (&x).into_iter() ==> x.iter()
1496
+ // (&mut x).into_iter() ==> x.iter_mut()
1497
+ match & arg. kind {
1498
+ ExprKind :: AddrOf ( mutability, arg_inner) if has_iter_method ( cx, cx. tables . expr_ty ( & arg_inner) ) . is_some ( ) => {
1499
+ let meth_name = match mutability {
1500
+ MutMutable => "iter_mut" ,
1501
+ MutImmutable => "iter" ,
1502
+ } ;
1503
+ format ! (
1504
+ "{}.{}()" ,
1505
+ sugg:: Sugg :: hir_with_applicability( cx, & arg_inner, "_" , applic_ref) . maybe_par( ) ,
1506
+ meth_name,
1507
+ )
1508
+ } ,
1509
+ _ => format ! (
1510
+ "{}.into_iter()" ,
1511
+ sugg:: Sugg :: hir_with_applicability( cx, arg, "_" , applic_ref) . maybe_par( )
1512
+ ) ,
1513
+ }
1514
+ }
1515
+ }
1516
+
1493
1517
/// Checks for the `FOR_KV_MAP` lint.
1494
1518
fn check_for_loop_over_map_kv < ' a , ' tcx > (
1495
1519
cx : & LateContext < ' a , ' tcx > ,
0 commit comments