about summary refs log tree commit diff
diff options
context:
space:
mode:
authordswij <dharmasw@outlook.com>2025-05-25 18:55:31 +0000
committerGitHub <noreply@github.com>2025-05-25 18:55:31 +0000
commit954034b4973fca154a346b39c8a8e628e31a146b (patch)
tree1ffe0cd4c3e7d8fa137191ed0bef6ecd7c32feaf
parentc12bc221671f18efec5f94bdcc684e762290d9b2 (diff)
parent7ffc886472f7b3d452306f6d2ae8efc29bbad084 (diff)
downloadrust-954034b4973fca154a346b39c8a8e628e31a146b.tar.gz
rust-954034b4973fca154a346b39c8a8e628e31a146b.zip
Fix `manual_find` suggests wrongly when return type needs adjustment (#14892)
Closes rust-lang/rust-clippy#14826

changelog: [`manual_find`] fix wrong suggestions when return type needs
adjustment
-rw-r--r--clippy_lints/src/loops/manual_find.rs7
-rw-r--r--tests/ui/manual_find_fixable.fixed10
-rw-r--r--tests/ui/manual_find_fixable.rs22
-rw-r--r--tests/ui/manual_find_fixable.stderr24
4 files changed, 62 insertions, 1 deletions
diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs
index 35737f3eafe..f99989ec6ba 100644
--- a/clippy_lints/src/loops/manual_find.rs
+++ b/clippy_lints/src/loops/manual_find.rs
@@ -83,6 +83,13 @@ pub(super) fn check<'tcx>(
                 )[..],
             );
         }
+
+        // If the return type requires adjustments, we need to add a `.map` after the iterator
+        let inner_ret_adjust = cx.typeck_results().expr_adjustments(inner_ret);
+        if !inner_ret_adjust.is_empty() {
+            snippet.push_str(".map(|v| v as _)");
+        }
+
         // Extends to `last_stmt` to include semicolon in case of `return None;`
         let lint_span = span.to(last_stmt.span).to(last_ret.span);
         span_lint_and_then(
diff --git a/tests/ui/manual_find_fixable.fixed b/tests/ui/manual_find_fixable.fixed
index 5e6849a4dfb..01b3ebacbeb 100644
--- a/tests/ui/manual_find_fixable.fixed
+++ b/tests/ui/manual_find_fixable.fixed
@@ -179,3 +179,13 @@ fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> {
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        ["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        ["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)
+    }
+}
diff --git a/tests/ui/manual_find_fixable.rs b/tests/ui/manual_find_fixable.rs
index 08a7dd2c6ee..ce62a4beba1 100644
--- a/tests/ui/manual_find_fixable.rs
+++ b/tests/ui/manual_find_fixable.rs
@@ -251,3 +251,25 @@ fn two_bindings(v: Vec<(u8, u8)>) -> Option<u8> {
 }
 
 fn main() {}
+
+mod issue14826 {
+    fn adjust_fixable(needle: &str) -> Option<&'static str> {
+        for candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+
+    fn adjust_unfixable(needle: &str) -> Option<*const str> {
+        for &candidate in &["foo", "bar"] {
+            //~^ manual_find
+            if candidate.eq_ignore_ascii_case(needle) {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+}
diff --git a/tests/ui/manual_find_fixable.stderr b/tests/ui/manual_find_fixable.stderr
index afa453c5a87..020635d90bb 100644
--- a/tests/ui/manual_find_fixable.stderr
+++ b/tests/ui/manual_find_fixable.stderr
@@ -139,5 +139,27 @@ LL | |                 return Some(x);
 LL | |         None
    | |____________^ help: replace with an iterator: `arr.into_iter().find(|&x| x < 1)`
 
-error: aborting due to 12 previous errors
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:257:9
+   |
+LL | /         for candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&candidate| candidate.eq_ignore_ascii_case(needle)).map(|v| v as _)`
+
+error: manual implementation of `Iterator::find`
+  --> tests/ui/manual_find_fixable.rs:267:9
+   |
+LL | /         for &candidate in &["foo", "bar"] {
+LL | |
+LL | |             if candidate.eq_ignore_ascii_case(needle) {
+LL | |                 return Some(candidate);
+...  |
+LL | |         None
+   | |____________^ help: replace with an iterator: `["foo", "bar"].iter().find(|&&candidate| candidate.eq_ignore_ascii_case(needle)).copied().map(|v| v as _)`
+
+error: aborting due to 14 previous errors