@@ -27,9 +27,10 @@ use syntax_pos::{BytePos, Symbol};
2727
2828use crate :: utils:: paths;
2929use 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 ,
3334} ;
3435
3536declare_clippy_lint ! {
@@ -1470,17 +1471,7 @@ fn check_for_loop_explicit_counter<'a, 'tcx>(
14701471 "for ({}, {}) in {}.enumerate()" ,
14711472 name,
14721473 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) ,
14841475 ) ,
14851476 applicability,
14861477 ) ;
@@ -1490,6 +1481,39 @@ fn check_for_loop_explicit_counter<'a, 'tcx>(
14901481 }
14911482}
14921483
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+
14931517/// Checks for the `FOR_KV_MAP` lint.
14941518fn check_for_loop_over_map_kv < ' a , ' tcx > (
14951519 cx : & LateContext < ' a , ' tcx > ,
0 commit comments