1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet;
3 use clippy_utils::ty::{get_iterator_item_ty, is_copy};
4 use itertools::Itertools;
5 use rustc_errors::Applicability;
7 use rustc_lint::LateContext;
11 use super::ITER_OVEREAGER_CLONED;
12 use crate::redundant_clone::REDUNDANT_CLONE;
14 /// lint overeager use of `cloned()` for `Iterator`s
15 pub(super) fn check<'tcx>(
16 cx: &LateContext<'tcx>,
17 expr: &'tcx hir::Expr<'_>,
18 recv: &'tcx hir::Expr<'_>,
20 map_arg: &[hir::Expr<'_>],
22 // Check if it's iterator and get type associated with `Item`.
23 let inner_ty = match get_iterator_item_ty(cx, cx.typeck_results().expr_ty_adjusted(recv)) {
28 match inner_ty.kind() {
29 ty::Ref(_, ty, _) if !is_copy(cx, ty) => {},
33 let (lint, preserve_cloned) = match name {
34 "count" => (REDUNDANT_CLONE, false),
35 _ => (ITER_OVEREAGER_CLONED, true),
37 let wildcard_params = map_arg.is_empty().not().then(|| "...").unwrap_or_default();
39 "called `cloned().{}({})` on an `Iterator`. It may be more efficient to call `{}({}){}` instead",
44 preserve_cloned.then(|| ".cloned()").unwrap_or_default(),
55 snippet(cx, recv.span, ".."),
57 map_arg.iter().map(|a| snippet(cx, a.span, "..")).join(", "),
58 preserve_cloned.then(|| ".cloned()").unwrap_or_default(),
60 Applicability::MachineApplicable,