about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakayuki Nakata <f.seasons017@gmail.com>2022-03-29 21:51:37 +0900
committerTakayuki Nakata <f.seasons017@gmail.com>2022-03-29 21:51:37 +0900
commitc22b7b8814e459d985c8ab337d933a4ae4feecea (patch)
tree8f8733b97cf68e4786939ca5cff87d334b7ad811
parent6206086dd5a83477131094b1f0ef61b10e7ced42 (diff)
downloadrust-c22b7b8814e459d985c8ab337d933a4ae4feecea.tar.gz
rust-c22b7b8814e459d985c8ab337d933a4ae4feecea.zip
Fix ICE for `iter_overeager_cloned`
-rw-r--r--clippy_lints/src/methods/iter_overeager_cloned.rs16
-rw-r--r--tests/ui/iter_overeager_cloned.fixed6
-rw-r--r--tests/ui/iter_overeager_cloned.rs6
-rw-r--r--tests/ui/iter_overeager_cloned.stderr14
4 files changed, 31 insertions, 11 deletions
diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs
index b93f1399eae..54c9ca435a4 100644
--- a/clippy_lints/src/methods/iter_overeager_cloned.rs
+++ b/clippy_lints/src/methods/iter_overeager_cloned.rs
@@ -1,11 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::ty::{get_iterator_item_ty, is_copy};
+use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy};
 use itertools::Itertools;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
+use rustc_span::sym;
 use std::ops::Not;
 
 use super::ITER_OVEREAGER_CLONED;
@@ -20,9 +21,16 @@ pub(super) fn check<'tcx>(
     map_arg: &[hir::Expr<'_>],
 ) {
     // Check if it's iterator and get type associated with `Item`.
-    let inner_ty = match get_iterator_item_ty(cx, cx.typeck_results().expr_ty_adjusted(recv)) {
-        Some(ty) => ty,
-        _ => return,
+    let inner_ty = if_chain! {
+        if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
+        let recv_ty = cx.typeck_results().expr_ty(recv);
+        if implements_trait(cx, recv_ty, iterator_trait_id, &[]);
+        if let Some(inner_ty) = get_iterator_item_ty(cx, cx.typeck_results().expr_ty_adjusted(recv));
+        then {
+            inner_ty
+        } else {
+            return;
+        }
     };
 
     match inner_ty.kind() {
diff --git a/tests/ui/iter_overeager_cloned.fixed b/tests/ui/iter_overeager_cloned.fixed
index a9041671101..56761ebbcb8 100644
--- a/tests/ui/iter_overeager_cloned.fixed
+++ b/tests/ui/iter_overeager_cloned.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
+#![allow(dead_code)]
 
 fn main() {
     let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()];
@@ -43,3 +44,8 @@ fn main() {
     // Should probably stay as it is.
     let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);
 }
+
+// #8527
+fn cloned_flatten(x: Option<&Option<String>>) -> Option<String> {
+    x.cloned().flatten()
+}
diff --git a/tests/ui/iter_overeager_cloned.rs b/tests/ui/iter_overeager_cloned.rs
index dd04e33a4b3..98321d889b5 100644
--- a/tests/ui/iter_overeager_cloned.rs
+++ b/tests/ui/iter_overeager_cloned.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 #![warn(clippy::iter_overeager_cloned, clippy::redundant_clone, clippy::filter_next)]
+#![allow(dead_code)]
 
 fn main() {
     let vec = vec!["1".to_string(), "2".to_string(), "3".to_string()];
@@ -45,3 +46,8 @@ fn main() {
     // Should probably stay as it is.
     let _ = [0, 1, 2, 3, 4].iter().cloned().take(10);
 }
+
+// #8527
+fn cloned_flatten(x: Option<&Option<String>>) -> Option<String> {
+    x.cloned().flatten()
+}
diff --git a/tests/ui/iter_overeager_cloned.stderr b/tests/ui/iter_overeager_cloned.stderr
index e36b0e36fbd..0582700fd16 100644
--- a/tests/ui/iter_overeager_cloned.stderr
+++ b/tests/ui/iter_overeager_cloned.stderr
@@ -1,5 +1,5 @@
 error: called `cloned().last()` on an `Iterator`. It may be more efficient to call `last().cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:7:29
+  --> $DIR/iter_overeager_cloned.rs:8:29
    |
 LL |     let _: Option<String> = vec.iter().cloned().last();
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().last().cloned()`
@@ -7,13 +7,13 @@ LL |     let _: Option<String> = vec.iter().cloned().last();
    = note: `-D clippy::iter-overeager-cloned` implied by `-D warnings`
 
 error: called `cloned().next()` on an `Iterator`. It may be more efficient to call `next().cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:9:29
+  --> $DIR/iter_overeager_cloned.rs:10:29
    |
 LL |     let _: Option<String> = vec.iter().chain(vec.iter()).cloned().next();
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().chain(vec.iter()).next().cloned()`
 
 error: called `cloned().count()` on an `Iterator`. It may be more efficient to call `count()` instead
-  --> $DIR/iter_overeager_cloned.rs:11:20
+  --> $DIR/iter_overeager_cloned.rs:12:20
    |
 LL |     let _: usize = vec.iter().filter(|x| x == &"2").cloned().count();
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().filter(|x| x == &"2").count()`
@@ -21,25 +21,25 @@ LL |     let _: usize = vec.iter().filter(|x| x == &"2").cloned().count();
    = note: `-D clippy::redundant-clone` implied by `-D warnings`
 
 error: called `cloned().take(...)` on an `Iterator`. It may be more efficient to call `take(...).cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:13:21
+  --> $DIR/iter_overeager_cloned.rs:14:21
    |
 LL |     let _: Vec<_> = vec.iter().cloned().take(2).collect();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().take(2).cloned()`
 
 error: called `cloned().skip(...)` on an `Iterator`. It may be more efficient to call `skip(...).cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:15:21
+  --> $DIR/iter_overeager_cloned.rs:16:21
    |
 LL |     let _: Vec<_> = vec.iter().cloned().skip(2).collect();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().skip(2).cloned()`
 
 error: called `cloned().nth(...)` on an `Iterator`. It may be more efficient to call `nth(...).cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:17:13
+  --> $DIR/iter_overeager_cloned.rs:18:13
    |
 LL |     let _ = vec.iter().filter(|x| x == &"2").cloned().nth(2);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec.iter().filter(|x| x == &"2").nth(2).cloned()`
 
 error: called `cloned().flatten()` on an `Iterator`. It may be more efficient to call `flatten().cloned()` instead
-  --> $DIR/iter_overeager_cloned.rs:19:13
+  --> $DIR/iter_overeager_cloned.rs:20:13
    |
 LL |       let _ = [Some(Some("str".to_string())), Some(Some("str".to_string()))]
    |  _____________^