diff options
| author | yanglsh <yanglsh@shanghaitech.edu.cn> | 2025-03-25 23:00:16 +0800 |
|---|---|---|
| committer | yanglsh <yanglsh@shanghaitech.edu.cn> | 2025-04-08 20:38:43 +0800 |
| commit | ee3612401121ccbdbf9c8d8fa6874c6e5128b049 (patch) | |
| tree | abcef4648e6ce8278ba733a0122c5fd6c8be601c | |
| parent | f74d7ce81371b2573d7a356408251fa4cac3f8d2 (diff) | |
| download | rust-ee3612401121ccbdbf9c8d8fa6874c6e5128b049.tar.gz rust-ee3612401121ccbdbf9c8d8fa6874c6e5128b049.zip | |
fix: `iter_cloned_collect` FP with custom `From`/`IntoIterator` impl
| -rw-r--r-- | clippy_lints/src/methods/iter_cloned_collect.rs | 10 | ||||
| -rw-r--r-- | tests/ui/iter_cloned_collect.fixed | 27 | ||||
| -rw-r--r-- | tests/ui/iter_cloned_collect.rs | 27 | ||||
| -rw-r--r-- | tests/ui/iter_cloned_collect.stderr | 8 |
4 files changed, 69 insertions, 3 deletions
diff --git a/clippy_lints/src/methods/iter_cloned_collect.rs b/clippy_lints/src/methods/iter_cloned_collect.rs index 49de83885a1..17cc07b91c5 100644 --- a/clippy_lints/src/methods/iter_cloned_collect.rs +++ b/clippy_lints/src/methods/iter_cloned_collect.rs @@ -1,16 +1,22 @@ use crate::methods::utils::derefs_to_slice; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::ty::is_type_diagnostic_item; +use clippy_utils::ty::{get_iterator_item_ty, is_type_diagnostic_item}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty; use rustc_span::sym; use super::ITER_CLONED_COLLECT; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir::Expr<'_>, recv: &'tcx hir::Expr<'_>) { - if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) + let expr_ty = cx.typeck_results().expr_ty(expr); + if is_type_diagnostic_item(cx, expr_ty, sym::Vec) && let Some(slice) = derefs_to_slice(cx, recv, cx.typeck_results().expr_ty(recv)) + && let ty::Adt(_, args) = expr_ty.kind() + && let Some(iter_item_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty(recv)) + && let ty::Ref(_, iter_item_ty, _) = iter_item_ty.kind() + && *iter_item_ty == args.type_at(0) && let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()) { span_lint_and_sugg( diff --git a/tests/ui/iter_cloned_collect.fixed b/tests/ui/iter_cloned_collect.fixed index e9fb44e8959..231fac7cdde 100644 --- a/tests/ui/iter_cloned_collect.fixed +++ b/tests/ui/iter_cloned_collect.fixed @@ -29,3 +29,30 @@ fn main() { let _: Vec<isize> = v.to_vec(); //~^ iter_cloned_collect } + +mod issue9119 { + + use std::iter; + + #[derive(Clone)] + struct Example(u16); + + impl iter::FromIterator<Example> for Vec<u8> { + fn from_iter<T>(iter: T) -> Self + where + T: IntoIterator<Item = Example>, + { + iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect() + } + } + + fn foo() { + let examples = [Example(1), Example(0x1234)]; + let encoded: Vec<u8> = examples.iter().cloned().collect(); + assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]); + + let a = [&&String::new()]; + let v: Vec<&&String> = a.to_vec(); + //~^ iter_cloned_collect + } +} diff --git a/tests/ui/iter_cloned_collect.rs b/tests/ui/iter_cloned_collect.rs index c9b8abcc9a0..e73b6ecae80 100644 --- a/tests/ui/iter_cloned_collect.rs +++ b/tests/ui/iter_cloned_collect.rs @@ -33,3 +33,30 @@ fn main() { let _: Vec<isize> = v.iter().copied().collect(); //~^ iter_cloned_collect } + +mod issue9119 { + + use std::iter; + + #[derive(Clone)] + struct Example(u16); + + impl iter::FromIterator<Example> for Vec<u8> { + fn from_iter<T>(iter: T) -> Self + where + T: IntoIterator<Item = Example>, + { + iter.into_iter().flat_map(|e| e.0.to_le_bytes()).collect() + } + } + + fn foo() { + let examples = [Example(1), Example(0x1234)]; + let encoded: Vec<u8> = examples.iter().cloned().collect(); + assert_eq!(encoded, vec![0x01, 0x00, 0x34, 0x12]); + + let a = [&&String::new()]; + let v: Vec<&&String> = a.iter().cloned().collect(); + //~^ iter_cloned_collect + } +} diff --git a/tests/ui/iter_cloned_collect.stderr b/tests/ui/iter_cloned_collect.stderr index 119698cb463..f8a50794327 100644 --- a/tests/ui/iter_cloned_collect.stderr +++ b/tests/ui/iter_cloned_collect.stderr @@ -36,5 +36,11 @@ error: called `iter().copied().collect()` on a slice to create a `Vec`. Calling LL | let _: Vec<isize> = v.iter().copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` -error: aborting due to 5 previous errors +error: called `iter().cloned().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and more readable + --> tests/ui/iter_cloned_collect.rs:59:33 + | +LL | let v: Vec<&&String> = a.iter().cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.to_vec()` + +error: aborting due to 6 previous errors |
