| use super::UNUSED_ENUMERATE_INDEX; |
| use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; |
| use clippy_utils::source::snippet; |
| use clippy_utils::{pat_is_wild, sugg}; |
| use rustc_hir::def::DefKind; |
| use rustc_hir::{Expr, ExprKind, Pat, PatKind}; |
| use rustc_lint::LateContext; |
| use rustc_middle::ty; |
| |
| /// Checks for the `UNUSED_ENUMERATE_INDEX` lint. |
| pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>, body: &'tcx Expr<'_>) { |
| let PatKind::Tuple([index, elem], _) = pat.kind else { |
| return; |
| }; |
| |
| let ExprKind::MethodCall(_method, self_arg, [], _) = arg.kind else { |
| return; |
| }; |
| |
| let ty = cx.typeck_results().expr_ty(arg); |
| |
| if !pat_is_wild(cx, &index.kind, body) { |
| return; |
| } |
| |
| let name = match *ty.kind() { |
| ty::Adt(base, _substs) => cx.tcx.def_path_str(base.did()), |
| _ => return, |
| }; |
| |
| if name != "std::iter::Enumerate" && name != "core::iter::Enumerate" { |
| return; |
| } |
| |
| let Some((DefKind::AssocFn, call_id)) = cx.typeck_results().type_dependent_def(arg.hir_id) else { |
| return; |
| }; |
| |
| let call_name = cx.tcx.def_path_str(call_id); |
| |
| if call_name != "std::iter::Iterator::enumerate" && call_name != "core::iter::Iterator::enumerate" { |
| return; |
| } |
| |
| span_lint_and_then( |
| cx, |
| UNUSED_ENUMERATE_INDEX, |
| arg.span, |
| "you seem to use `.enumerate()` and immediately discard the index", |
| |diag| { |
| let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter"); |
| multispan_sugg( |
| diag, |
| "remove the `.enumerate()` call", |
| vec![ |
| (pat.span, snippet(cx, elem.span, "..").into_owned()), |
| (arg.span, base_iter.to_string()), |
| ], |
| ); |
| }, |
| ); |
| } |