]> git.proxmox.com Git - rustc.git/blob - src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / methods / iter_overeager_cloned.rs
1 use clippy_utils::diagnostics::span_lint_and_then;
2 use clippy_utils::source::snippet_opt;
3 use clippy_utils::ty::{implements_trait, is_copy};
4 use rustc_errors::Applicability;
5 use rustc_hir::Expr;
6 use rustc_lint::LateContext;
7 use rustc_middle::ty;
8 use rustc_span::sym;
9
10 use super::ITER_OVEREAGER_CLONED;
11 use crate::redundant_clone::REDUNDANT_CLONE;
12
13 pub(super) fn check<'tcx>(
14 cx: &LateContext<'tcx>,
15 expr: &'tcx Expr<'_>,
16 cloned_call: &'tcx Expr<'_>,
17 cloned_recv: &'tcx Expr<'_>,
18 is_count: bool,
19 needs_into_iter: bool,
20 ) {
21 let typeck = cx.typeck_results();
22 if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator)
23 && let Some(method_id) = typeck.type_dependent_def_id(expr.hir_id)
24 && cx.tcx.trait_of_item(method_id) == Some(iter_id)
25 && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id)
26 && cx.tcx.trait_of_item(method_id) == Some(iter_id)
27 && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv)
28 && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item")
29 && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty))
30 {
31 if needs_into_iter
32 && let Some(into_iter_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator)
33 && !implements_trait(cx, iter_assoc_ty, into_iter_id, &[])
34 {
35 return;
36 }
37
38 let (lint, msg, trailing_clone) = if is_count {
39 (REDUNDANT_CLONE, "unneeded cloning of iterator items", "")
40 } else {
41 (ITER_OVEREAGER_CLONED, "unnecessarily eager cloning of iterator items", ".cloned()")
42 };
43
44 span_lint_and_then(
45 cx,
46 lint,
47 expr.span,
48 msg,
49 |diag| {
50 let method_span = expr.span.with_lo(cloned_call.span.hi());
51 if let Some(mut snip) = snippet_opt(cx, method_span) {
52 snip.push_str(trailing_clone);
53 let replace_span = expr.span.with_lo(cloned_recv.span.hi());
54 diag.span_suggestion(replace_span, "try this", snip, Applicability::MachineApplicable);
55 }
56 }
57 );
58 }
59 }