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
;
6 use rustc_lint
::LateContext
;
10 use super::ITER_OVEREAGER_CLONED
;
11 use crate::redundant_clone
::REDUNDANT_CLONE
;
13 pub(super) fn check
<'tcx
>(
14 cx
: &LateContext
<'tcx
>,
16 cloned_call
: &'tcx Expr
<'_
>,
17 cloned_recv
: &'tcx Expr
<'_
>,
19 needs_into_iter
: bool
,
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
))
32 && let Some(into_iter_id
) = cx
.tcx
.get_diagnostic_item(sym
::IntoIterator
)
33 && !implements_trait(cx
, iter_assoc_ty
, into_iter_id
, &[])
38 let (lint
, msg
, trailing_clone
) = if is_count
{
39 (REDUNDANT_CLONE
, "unneeded cloning of iterator items", "")
41 (ITER_OVEREAGER_CLONED
, "unnecessarily eager cloning of iterator items", ".cloned()")
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
);