Skip to content

Commit c960290

Browse files
committed
fix: iter_cloned_collect FP with custom From/IntoIterator impl
1 parent f5d81a3 commit c960290

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

clippy_lints/src/methods/iter_cloned_collect.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
use crate::methods::utils::derefs_to_slice;
22
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::ty::is_type_diagnostic_item;
3+
use clippy_utils::ty::{get_iterator_item_ty, is_type_diagnostic_item};
44
use rustc_errors::Applicability;
55
use rustc_hir as hir;
66
use rustc_lint::LateContext;
7+
use rustc_middle::ty;
78
use rustc_span::sym;
89

910
use super::ITER_CLONED_COLLECT;
1011

1112
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) {
12-
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec)
13+
let expr_ty = cx.typeck_results().expr_ty(expr);
14+
if is_type_diagnostic_item(cx, expr_ty, sym::Vec)
1315
&& let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv))
16+
&& let ty::Adt(_, args) = expr_ty.kind()
17+
&& let Some(iter_item_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv))
18+
&& iter_item_ty.peel_refs() == args.type_at(0)
1419
&& let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite())
1520
{
1621
span_lint_and_sugg(

tests/ui/iter_cloned_collect.fixed

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,26 @@ fn main() {
2929
let _: Vec<isize> = v.to_vec();
3030
//~^ iter_cloned_collect
3131
}
32+
33+
mod issue9119 {
34+
35+
use std::iter;
36+
37+
#[derive(Clone)]
38+
struct Example(u16);
39+
40+
impl iter::FromIterator<Example> for Vec<u8> {
41+
fn from_iter<T>(iter: T) -> Self
42+
where
43+
T: IntoIterator<Item = Example>,
44+
{
45+
iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
46+
}
47+
}
48+
49+
fn foo() {
50+
let examples = [Example(1), Example(0x1234)];
51+
let encoded: Vec<u8> = examples.iter().cloned().collect();
52+
assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
53+
}
54+
}

tests/ui/iter_cloned_collect.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,26 @@ fn main() {
3333
let _: Vec<isize> = v.iter().copied().collect();
3434
//~^ iter_cloned_collect
3535
}
36+
37+
mod issue9119 {
38+
39+
use std::iter;
40+
41+
#[derive(Clone)]
42+
struct Example(u16);
43+
44+
impl iter::FromIterator<Example> for Vec<u8> {
45+
fn from_iter<T>(iter: T) -> Self
46+
where
47+
T: IntoIterator<Item = Example>,
48+
{
49+
iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect()
50+
}
51+
}
52+
53+
fn foo() {
54+
let examples = [Example(1), Example(0x1234)];
55+
let encoded: Vec<u8> = examples.iter().cloned().collect();
56+
assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]);
57+
}
58+
}

0 commit comments

Comments
 (0)