blob: dd7fae79d9ba842aa78b3cdf523328e4d0f8a974 [file] [log] [blame]
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()),
],
);
},
);
}