]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/methods/iter_overeager_cloned.rs
Split out `infalliable_detructuring_match`
[rust.git] / clippy_lints / src / methods / iter_overeager_cloned.rs
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;
6 use rustc_hir as hir;
7 use rustc_lint::LateContext;
8 use rustc_middle::ty;
9 use std::ops::Not;
10
11 use super::ITER_OVEREAGER_CLONED;
12 use crate::redundant_clone::REDUNDANT_CLONE;
13
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<'_>,
19     name: &str,
20     map_arg: &[hir::Expr<'_>],
21 ) {
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)) {
24         Some(ty) => ty,
25         _ => return,
26     };
27
28     match inner_ty.kind() {
29         ty::Ref(_, ty, _) if !is_copy(cx, ty) => {},
30         _ => return,
31     };
32
33     let (lint, preserve_cloned) = match name {
34         "count" => (REDUNDANT_CLONE, false),
35         _ => (ITER_OVEREAGER_CLONED, true),
36     };
37     let wildcard_params = map_arg.is_empty().not().then(|| "...").unwrap_or_default();
38     let msg = format!(
39         "called `cloned().{}({})` on an `Iterator`. It may be more efficient to call `{}({}){}` instead",
40         name,
41         wildcard_params,
42         name,
43         wildcard_params,
44         preserve_cloned.then(|| ".cloned()").unwrap_or_default(),
45     );
46
47     span_lint_and_sugg(
48         cx,
49         lint,
50         expr.span,
51         &msg,
52         "try this",
53         format!(
54             "{}.{}({}){}",
55             snippet(cx, recv.span, ".."),
56             name,
57             map_arg.iter().map(|a| snippet(cx, a.span, "..")).join(", "),
58             preserve_cloned.then(|| ".cloned()").unwrap_or_default(),
59         ),
60         Applicability::MachineApplicable,
61     );
62 }