about summary refs log tree commit diff
diff options
context:
space:
mode:
authoryanglsh <yanglsh@shanghaitech.edu.cn>2025-05-25 15:05:05 +0800
committeryanglsh <yanglsh@shanghaitech.edu.cn>2025-05-25 15:05:05 +0800
commit7ffc886472f7b3d452306f6d2ae8efc29bbad084 (patch)
treedee47884c740982e85643e94f946e5d1e1134e29
parentb6b97a741cad25bb9cd3250544b6fe06a1ab59cd (diff)
downloadrust-7ffc886472f7b3d452306f6d2ae8efc29bbad084.tar.gz
rust-7ffc886472f7b3d452306f6d2ae8efc29bbad084.zip
fix: `manual_find` suggests wrongly 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