about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/methods/iter_overeager_cloned.rs5
-rw-r--r--clippy_lints/src/methods/mod.rs26
-rw-r--r--tests/ui/iter_overeager_cloned.fixed12
-rw-r--r--tests/ui/iter_overeager_cloned.rs12
-rw-r--r--tests/ui/iter_overeager_cloned.stderr4
7 files changed, 44 insertions, 17 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a9be021437..3f26b9470e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6553,6 +6553,7 @@ Released 2018-09-13
 [`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names
 [`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
 [`redundant_guards`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_guards
+[`redundant_iter_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_iter_cloned
 [`redundant_locals`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_locals
 [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern
 [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 1b19a8851ed..2a4bedc1845 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -453,6 +453,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[
     crate::methods::READONLY_WRITE_LOCK_INFO,
     crate::methods::READ_LINE_WITHOUT_TRIM_INFO,
     crate::methods::REDUNDANT_AS_STR_INFO,
+    crate::methods::REDUNDANT_ITER_CLONED_INFO,
     crate::methods::REPEAT_ONCE_INFO,
     crate::methods::RESULT_FILTER_MAP_INFO,
     crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO,
diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs
index f851ebe91f3..d43dc23a86b 100644
--- a/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -10,8 +10,7 @@ use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty::{self, BorrowKind};
 use rustc_span::{Symbol, sym};
 
-use super::ITER_OVEREAGER_CLONED;
-use crate::redundant_clone::REDUNDANT_CLONE;
+use super::{ITER_OVEREAGER_CLONED, REDUNDANT_ITER_CLONED};
 
 #[derive(Clone, Copy)]
 pub(super) enum Op<'a> {
@@ -96,7 +95,7 @@ pub(super) fn check<'tcx>(
         }
 
         let (lint, msg, trailing_clone) = match op {
-            Op::RmCloned | Op::NeedlessMove(_) => (REDUNDANT_CLONE, "unneeded cloning of iterator items", ""),
+            Op::RmCloned | Op::NeedlessMove(_) => (REDUNDANT_ITER_CLONED, "unneeded cloning of iterator items", ""),
             Op::LaterCloned | Op::FixClosure(_, _) => (
                 ITER_OVEREAGER_CLONED,
                 "unnecessarily eager cloning of iterator items",
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index d06b0ed64bd..8679689c8ad 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -4614,6 +4614,31 @@ declare_clippy_lint! {
     "hardcoded localhost IP address"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for calls to `Iterator::cloned` where the original value could be used
+    /// instead.
+    ///
+    /// ### Why is this bad?
+    /// It is not always possible for the compiler to eliminate useless allocations and
+    /// deallocations generated by redundant `clone()`s.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let x = vec![String::new()];
+    /// let _ = x.iter().cloned().map(|x| x.len());
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// let x = vec![String::new()];
+    /// let _ = x.iter().map(|x| x.len());
+    /// ```
+    #[clippy::version = "1.90.0"]
+    pub REDUNDANT_ITER_CLONED,
+    perf,
+    "detects redundant calls to `Iterator::cloned`"
+}
+
 #[expect(clippy::struct_excessive_bools)]
 pub struct Methods {
     avoid_breaking_exported_api: bool,
@@ -4794,6 +4819,7 @@ impl_lint_pass!(Methods => [
     IO_OTHER_ERROR,
     SWAP_WITH_TEMPORARY,
     IP_CONSTANT,
+    REDUNDANT_ITER_CLONED,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed
index b0e548f1790..4171f19469a 100644
--- a/tests/ui/iter_overeager_cloned.fixed
+++ b/tests/ui/iter_overeager_cloned.fixed
@@ -1,4 +1,4 @@
-#![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
+#![warn(clippy::iter_overeager_cloned, clippy::redundant_iter_cloned, clippy::filter_next)]
 #![allow(
     dead_code,
     clippy::let_unit_value,
@@ -16,7 +16,7 @@ fn main() {
     //~^ iter_overeager_cloned
 
     let _: usize = vec.iter().filter(|x| x == &"2").count();
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _: Vec<_> = vec.iter().take(2).cloned().collect();
     //~^ iter_overeager_cloned
@@ -77,19 +77,19 @@ fn main() {
     }
 
     let _ = vec.iter().map(|x| x.len());
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     // This would fail if changed.
     let _ = vec.iter().cloned().map(|x| x + "2");
 
     let _ = vec.iter().for_each(|x| assert!(!x.is_empty()));
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _ = vec.iter().all(|x| x.len() == 1);
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _ = vec.iter().any(|x| x.len() == 1);
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     // Should probably stay as it is.
     let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);
diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs
index cedf62a6b47..fe6aba24dd3 100644
--- a/tests/ui/iter_overeager_cloned.rs
+++ b/tests/ui/iter_overeager_cloned.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
+#![warn(clippy::iter_overeager_cloned, clippy::redundant_iter_cloned, clippy::filter_next)]
 #![allow(
     dead_code,
     clippy::let_unit_value,
@@ -16,7 +16,7 @@ fn main() {
     //~^ iter_overeager_cloned
 
     let _: usize = vec.iter().filter(|x| x == &"2").cloned().count();
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _: Vec<_> = vec.iter().cloned().take(2).collect();
     //~^ iter_overeager_cloned
@@ -78,19 +78,19 @@ fn main() {
     }
 
     let _ = vec.iter().cloned().map(|x| x.len());
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     // This would fail if changed.
     let _ = vec.iter().cloned().map(|x| x + "2");
 
     let _ = vec.iter().cloned().for_each(|x| assert!(!x.is_empty()));
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _ = vec.iter().cloned().all(|x| x.len() == 1);
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     let _ = vec.iter().cloned().any(|x| x.len() == 1);
-    //~^ redundant_clone
+    //~^ redundant_iter_cloned
 
     // Should probably stay as it is.
     let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);
diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr
index 1616dec95b7..f234d19e4aa 100644
--- a/tests/ui/iter_overeager_cloned.stderr
+++ b/tests/ui/iter_overeager_cloned.stderr
@@ -25,8 +25,8 @@ LL |     let _: usize = vec.iter().filter(|x| x == &"2").cloned().count();
    |                                                    |
    |                                                    help: try: `.count()`
    |
-   = note: `-D clippy::redundant-clone` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]`
+   = note: `-D clippy::redundant-iter-cloned` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::redundant_iter_cloned)]`
 
 error: unnecessarily eager cloning of iterator items
   --> tests/ui/iter_overeager_cloned.rs:21:21