From 3807905e08a8b5bee2160766d12b12ea4e71392f Mon Sep 17 00:00:00 2001
From: "Samuel E. Moelius III" <sam@moeli.us>
Date: Mon, 13 Dec 2021 05:49:43 -0500
Subject: [PATCH] Handle `to_vec` on for loop expression #8069

---
 clippy_lints/src/methods/mod.rs               |   1 +
 .../src/methods/unnecessary_iter_cloned.rs    | 177 +++++++++++++++
 .../src/methods/unnecessary_to_owned.rs       | 149 ++++++++-----
 clippy_utils/src/ty.rs                        |  22 +-
 clippy_utils/src/usage.rs                     |   2 +-
 tests/ui/unnecessary_iter_cloned.fixed        | 142 ++++++++++++
 tests/ui/unnecessary_iter_cloned.rs           | 142 ++++++++++++
 tests/ui/unnecessary_iter_cloned.stderr       |  35 +++
 tests/ui/unnecessary_to_owned.fixed           |  45 +++-
 tests/ui/unnecessary_to_owned.rs              |  45 +++-
 tests/ui/unnecessary_to_owned.stderr          | 208 ++++++++++++------
 11 files changed, 829 insertions(+), 139 deletions(-)
 create mode 100644 clippy_lints/src/methods/unnecessary_iter_cloned.rs
 create mode 100644 tests/ui/unnecessary_iter_cloned.fixed
 create mode 100644 tests/ui/unnecessary_iter_cloned.rs
 create mode 100644 tests/ui/unnecessary_iter_cloned.stderr

diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index a0de296fd07..6a61e662698 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -56,6 +56,7 @@ mod suspicious_splitn;
 mod uninit_assumed_init;
 mod unnecessary_filter_map;
 mod unnecessary_fold;
+mod unnecessary_iter_cloned;
 mod unnecessary_lazy_eval;
 mod unnecessary_to_owned;
 mod unwrap_or_else_default;
diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
new file mode 100644
index 00000000000..8300df03e99
--- /dev/null
+++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -0,0 +1,177 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher::ForLoop;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
+use clippy_utils::{fn_def_id, get_parent_expr, path_to_local_id, usage};
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, HirId, LangItem, Mutability, Pat};
+use rustc_lint::LateContext;
+use rustc_middle::{hir::map::Map, ty};
+use rustc_span::{sym, Symbol};
+
+use super::UNNECESSARY_TO_OWNED;
+
+pub fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: Symbol, receiver: &'tcx Expr<'tcx>) -> bool {
+    if_chain! {
+        if let Some(parent) = get_parent_expr(cx, expr);
+        if let Some(callee_def_id) = fn_def_id(cx, parent);
+        if is_into_iter(cx, callee_def_id);
+        then {
+            check_for_loop_iter(cx, parent, method_name, receiver)
+        } else {
+            false
+        }
+    }
+}
+
+/// Checks whether `expr` is an iterator in a `for` loop and, if so, determines whether the
+/// iterated-over items could be iterated over by reference. The reason why `check` above does not
+/// include this code directly is so that it can be called from
+/// `unnecessary_into_owned::check_into_iter_call_arg`.
+pub fn check_for_loop_iter(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    method_name: Symbol,
+    receiver: &'tcx Expr<'tcx>,
+) -> bool {
+    if_chain! {
+        if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent));
+        if let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent);
+        let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body);
+        if !clone_or_copy_needed;
+        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
+        then {
+            let snippet = if_chain! {
+                if let ExprKind::MethodCall(maybe_iter_method_name, _, [collection], _) = receiver.kind;
+                if maybe_iter_method_name.ident.name == sym::iter;
+
+                if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
+                let receiver_ty = cx.typeck_results().expr_ty(receiver);
+                if implements_trait(cx, receiver_ty, iterator_trait_id, &[]);
+                if let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty);
+
+                if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator);
+                let collection_ty = cx.typeck_results().expr_ty(collection);
+                if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]);
+                if let Some(into_iter_item_ty) = get_associated_type(cx, collection_ty, into_iterator_trait_id, "Item");
+
+                if iter_item_ty == into_iter_item_ty;
+                if let Some(collection_snippet) = snippet_opt(cx, collection.span);
+                then {
+                    collection_snippet
+                } else {
+                    receiver_snippet
+                }
+            };
+            span_lint_and_then(
+                cx,
+                UNNECESSARY_TO_OWNED,
+                expr.span,
+                &format!("unnecessary use of `{}`", method_name),
+                |diag| {
+                    diag.span_suggestion(expr.span, "use", snippet, Applicability::MachineApplicable);
+                    for addr_of_expr in addr_of_exprs {
+                        match addr_of_expr.kind {
+                            ExprKind::AddrOf(_, _, referent) => {
+                                let span = addr_of_expr.span.with_hi(referent.span.lo());
+                                diag.span_suggestion(span, "remove this `&`", String::new(), Applicability::MachineApplicable);
+                            }
+                            _ => unreachable!(),
+                        }
+                    }
+                }
+            );
+            return true;
+        }
+    }
+    false
+}
+
+/// The core logic of `check_for_loop_iter` above, this function wraps a use of
+/// `CloneOrCopyVisitor`.
+fn clone_or_copy_needed(
+    cx: &LateContext<'tcx>,
+    pat: &Pat<'tcx>,
+    body: &'tcx Expr<'tcx>,
+) -> (bool, Vec<&'tcx Expr<'tcx>>) {
+    let mut visitor = CloneOrCopyVisitor {
+        cx,
+        binding_hir_ids: pat_bindings(pat),
+        clone_or_copy_needed: false,
+        addr_of_exprs: Vec::new(),
+    };
+    visitor.visit_expr(body);
+    (visitor.clone_or_copy_needed, visitor.addr_of_exprs)
+}
+
+/// Returns a vector of all `HirId`s bound by the pattern.
+fn pat_bindings(pat: &Pat<'_>) -> Vec<HirId> {
+    let mut collector = usage::ParamBindingIdCollector {
+        binding_hir_ids: Vec::new(),
+    };
+    collector.visit_pat(pat);
+    collector.binding_hir_ids
+}
+
+/// `clone_or_copy_needed` will be false when `CloneOrCopyVisitor` is done visiting if the only
+/// operations performed on `binding_hir_ids` are:
+/// * to take non-mutable references to them
+/// * to use them as non-mutable `&self` in method calls
+/// If any of `binding_hir_ids` is used in any other way, then `clone_or_copy_needed` will be true
+/// when `CloneOrCopyVisitor` is done visiting.
+struct CloneOrCopyVisitor<'cx, 'tcx> {
+    cx: &'cx LateContext<'tcx>,
+    binding_hir_ids: Vec<HirId>,
+    clone_or_copy_needed: bool,
+    addr_of_exprs: Vec<&'tcx Expr<'tcx>>,
+}
+
+impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        walk_expr(self, expr);
+        if self.is_binding(expr) {
+            if let Some(parent) = get_parent_expr(self.cx, expr) {
+                match parent.kind {
+                    ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) => {
+                        self.addr_of_exprs.push(parent);
+                        return;
+                    },
+                    ExprKind::MethodCall(_, _, args, _) => {
+                        if_chain! {
+                            if args.iter().skip(1).all(|arg| !self.is_binding(arg));
+                            if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
+                            let method_ty = self.cx.tcx.type_of(method_def_id);
+                            let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
+                            if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not));
+                            then {
+                                return;
+                            }
+                        }
+                    },
+                    _ => {},
+                }
+            }
+            self.clone_or_copy_needed = true;
+        }
+    }
+}
+
+impl<'cx, 'tcx> CloneOrCopyVisitor<'cx, 'tcx> {
+    fn is_binding(&self, expr: &Expr<'tcx>) -> bool {
+        self.binding_hir_ids
+            .iter()
+            .any(|hir_id| path_to_local_id(expr, *hir_id))
+    }
+}
+
+/// Returns true if the named method is `IntoIterator::into_iter`.
+pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
+    cx.tcx.lang_items().require(LangItem::IntoIterIntoIter) == Ok(callee_def_id)
+}
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index b380f734bff..c5af7483ae6 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -1,8 +1,9 @@
 use super::implicit_clone::is_clone_like;
+use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{implements_trait, is_copy, peel_mid_ty_refs};
-use clippy_utils::{get_parent_expr, is_diag_item_method, is_diag_trait_item};
+use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
+use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item};
 use rustc_errors::Applicability;
 use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -18,17 +19,23 @@ use super::UNNECESSARY_TO_OWNED;
 pub fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: Symbol, args: &'tcx [Expr<'tcx>]) {
     if_chain! {
         if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
-        if is_to_owned_like(cx, method_name, method_def_id);
         if let [receiver] = args;
         then {
-            // At this point, we know the call is of a `to_owned`-like function. The functions
-            // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
-            // based on its context, that is, whether it is a referent in an `AddrOf` expression or
-            // an argument in a function call.
-            if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
-                return;
+            if is_cloned_or_copied(cx, method_name, method_def_id) {
+                unnecessary_iter_cloned::check(cx, expr, method_name, receiver);
+            } else if is_to_owned_like(cx, method_name, method_def_id) {
+                // At this point, we know the call is of a `to_owned`-like function. The functions
+                // `check_addr_of_expr` and `check_call_arg` determine whether the call is unnecessary
+                // based on its context, that is, whether it is a referent in an `AddrOf` expression, an
+                // argument in a `into_iter` call, or an argument in the call of some other function.
+                if check_addr_of_expr(cx, expr, method_name, method_def_id, receiver) {
+                    return;
+                }
+                if check_into_iter_call_arg(cx, expr, method_name, receiver) {
+                    return;
+                }
+                check_other_call_arg(cx, expr, method_name, receiver);
             }
-            check_call_arg(cx, expr, method_name, receiver);
         }
     }
 }
@@ -116,29 +123,34 @@ fn check_addr_of_expr(
                     return true;
                 }
             }
-            if implements_deref_trait(cx, receiver_ty, target_ty) {
-                if n_receiver_refs > 0 {
-                    span_lint_and_sugg(
-                        cx,
-                        UNNECESSARY_TO_OWNED,
-                        parent.span,
-                        &format!("unnecessary use of `{}`", method_name),
-                        "use",
-                        receiver_snippet,
-                        Applicability::MachineApplicable,
-                    );
-                } else {
-                    span_lint_and_sugg(
-                        cx,
-                        UNNECESSARY_TO_OWNED,
-                        expr.span.with_lo(receiver.span.hi()),
-                        &format!("unnecessary use of `{}`", method_name),
-                        "remove this",
-                        String::new(),
-                        Applicability::MachineApplicable,
-                    );
+            if_chain! {
+                if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
+                if implements_trait(cx, receiver_ty, deref_trait_id, &[]);
+                if get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(target_ty);
+                then {
+                    if n_receiver_refs > 0 {
+                        span_lint_and_sugg(
+                            cx,
+                            UNNECESSARY_TO_OWNED,
+                            parent.span,
+                            &format!("unnecessary use of `{}`", method_name),
+                            "use",
+                            receiver_snippet,
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        span_lint_and_sugg(
+                            cx,
+                            UNNECESSARY_TO_OWNED,
+                            expr.span.with_lo(receiver.span.hi()),
+                            &format!("unnecessary use of `{}`", method_name),
+                            "remove this",
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                    return true;
                 }
-                return true;
             }
             if_chain! {
                 if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef);
@@ -161,9 +173,55 @@ fn check_addr_of_expr(
     false
 }
 
+/// Checks whether `expr` is an argument in an `into_iter` call and, if so, determines whether its
+/// call of a `to_owned`-like function is unnecessary.
+fn check_into_iter_call_arg(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    method_name: Symbol,
+    receiver: &'tcx Expr<'tcx>,
+) -> bool {
+    if_chain! {
+        if let Some(parent) = get_parent_expr(cx, expr);
+        if let Some(callee_def_id) = fn_def_id(cx, parent);
+        if is_into_iter(cx, callee_def_id);
+        if let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
+        let parent_ty = cx.typeck_results().expr_ty(parent);
+        if implements_trait(cx, parent_ty, iterator_trait_id, &[]);
+        if let Some(item_ty) = get_iterator_item_ty(cx, parent_ty);
+        if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
+        then {
+            if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver) {
+                return true;
+            }
+            let cloned_or_copied = if is_copy(cx, item_ty) {
+                "copied"
+            } else {
+                "cloned"
+            };
+            span_lint_and_sugg(
+                cx,
+                UNNECESSARY_TO_OWNED,
+                parent.span,
+                &format!("unnecessary use of `{}`", method_name),
+                "use",
+                format!("{}.iter().{}()", receiver_snippet, cloned_or_copied),
+                Applicability::MachineApplicable,
+            );
+            return true;
+        }
+    }
+    false
+}
+
 /// Checks whether `expr` is an argument in a function call and, if so, determines whether its call
 /// of a `to_owned`-like function is unnecessary.
-fn check_call_arg(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: Symbol, receiver: &'tcx Expr<'tcx>) {
+fn check_other_call_arg(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'tcx>,
+    method_name: Symbol,
+    receiver: &'tcx Expr<'tcx>,
+) -> bool {
     if_chain! {
         if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr);
         if let Some((callee_def_id, call_substs, call_args)) = get_callee_substs_and_args(cx, maybe_call);
@@ -186,7 +244,8 @@ fn check_call_arg(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: S
             if let [projection_predicate] = projection_predicates[..] {
                 let normalized_ty =
                     cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty);
-                implements_deref_trait(cx, receiver_ty, normalized_ty)
+                implements_trait(cx, receiver_ty, deref_trait_id, &[])
+                    && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty)
             } else {
                 false
             }
@@ -215,8 +274,10 @@ fn check_call_arg(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: S
                 format!("{:&>width$}{}", "", receiver_snippet, width = n_refs),
                 Applicability::MachineApplicable,
             );
+            return true;
         }
     }
+    false
 }
 
 /// Walks an expression's ancestors until it finds a non-`AddrOf` expression. Returns the first such
@@ -315,22 +376,10 @@ fn compose_substs(cx: &LateContext<'tcx>, left: &[GenericArg<'tcx>], right: Subs
         .collect()
 }
 
-/// Helper function to check whether a type implements the `Deref` trait.
-fn implements_deref_trait(cx: &LateContext<'tcx>, ty: Ty<'tcx>, deref_target_ty: Ty<'tcx>) -> bool {
-    if_chain! {
-        if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref);
-        if implements_trait(cx, ty, deref_trait_id, &[]);
-        if let Some(deref_target_id) = cx.tcx.lang_items().deref_target();
-        let substs = cx.tcx.mk_substs_trait(ty, &[]);
-        let projection_ty = cx.tcx.mk_projection(deref_target_id, substs);
-        let normalized_ty = cx.tcx.normalize_erasing_regions(cx.param_env, projection_ty);
-        if normalized_ty == deref_target_ty;
-        then {
-            true
-        } else {
-            false
-        }
-    }
+/// Returns true if the named method is `Iterator::cloned` or `Iterator::copied`.
+fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id: DefId) -> bool {
+    (method_name.as_str() == "cloned" || method_name.as_str() == "copied")
+        && is_diag_trait_item(cx, method_def_id, sym::Iterator)
 }
 
 /// Returns true if the named method can be used to convert the receiver to its "owned"
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 438c39bea0a..6d191d4a59b 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -58,14 +58,20 @@ pub fn contains_adt_constructor<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, adt: &'tc
 pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     cx.tcx
         .get_diagnostic_item(sym::Iterator)
-        .and_then(|iter_did| {
-            cx.tcx.associated_items(iter_did).find_by_name_and_kind(
-                cx.tcx,
-                Ident::from_str("Item"),
-                ty::AssocKind::Type,
-                iter_did,
-            )
-        })
+        .and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item"))
+}
+
+/// Returns the associated type `name` for `ty` as an implementation of `trait_id`.
+/// Do not invoke without first verifying that the type implements the trait.
+pub fn get_associated_type<'tcx>(
+    cx: &LateContext<'tcx>,
+    ty: Ty<'tcx>,
+    trait_id: DefId,
+    name: &str,
+) -> Option<Ty<'tcx>> {
+    cx.tcx
+        .associated_items(trait_id)
+        .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
         .map(|assoc| {
             let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, &[]));
             cx.tcx.normalize_erasing_regions(cx.param_env, proj)
diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs
index dfe8a66c2a1..2066915e1d1 100644
--- a/clippy_utils/src/usage.rs
+++ b/clippy_utils/src/usage.rs
@@ -78,7 +78,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
 }
 
 pub struct ParamBindingIdCollector {
-    binding_hir_ids: Vec<hir::HirId>,
+    pub binding_hir_ids: Vec<hir::HirId>,
 }
 impl<'tcx> ParamBindingIdCollector {
     fn collect_binding_hir_ids(body: &'tcx hir::Body<'tcx>) -> Vec<hir::HirId> {
diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed
new file mode 100644
index 00000000000..e01e9f07baf
--- /dev/null
+++ b/tests/ui/unnecessary_iter_cloned.fixed
@@ -0,0 +1,142 @@
+// run-rustfix
+
+#![allow(unused_assignments)]
+#![warn(clippy::unnecessary_to_owned)]
+
+#[allow(dead_code)]
+#[derive(Clone, Copy)]
+enum FileType {
+    Account,
+    PrivateKey,
+    Certificate,
+}
+
+fn main() {
+    let path = std::path::Path::new("x");
+
+    let _ = check_files(&[(FileType::Account, path)]);
+    let _ = check_files_vec(vec![(FileType::Account, path)]);
+
+    // negative tests
+    let _ = check_files_ref(&[(FileType::Account, path)]);
+    let _ = check_files_mut(&[(FileType::Account, path)]);
+    let _ = check_files_ref_mut(&[(FileType::Account, path)]);
+    let _ = check_files_self_and_arg(&[(FileType::Account, path)]);
+    let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]);
+}
+
+// `check_files` and its variants are based on:
+// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
+fn check_files(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (t, path) in files {
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool {
+    for (t, path) in files.iter() {
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_ref(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (ref t, path) in files.iter().copied() {
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+#[allow(unused_assignments)]
+fn check_files_mut(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (mut t, path) in files.iter().copied() {
+        t = FileType::PrivateKey;
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_ref_mut(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (ref mut t, path) in files.iter().copied() {
+        *t = FileType::PrivateKey;
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_self_and_arg(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (t, path) in files.iter().copied() {
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.join(path).is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+#[allow(unused_assignments)]
+fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
+    for (mut t, path) in files.iter().cloned() {
+        t = FileType::PrivateKey;
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
+    Ok(std::path::PathBuf::new())
+}
diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs
new file mode 100644
index 00000000000..6ef2966c8b7
--- /dev/null
+++ b/tests/ui/unnecessary_iter_cloned.rs
@@ -0,0 +1,142 @@
+// run-rustfix
+
+#![allow(unused_assignments)]
+#![warn(clippy::unnecessary_to_owned)]
+
+#[allow(dead_code)]
+#[derive(Clone, Copy)]
+enum FileType {
+    Account,
+    PrivateKey,
+    Certificate,
+}
+
+fn main() {
+    let path = std::path::Path::new("x");
+
+    let _ = check_files(&[(FileType::Account, path)]);
+    let _ = check_files_vec(vec![(FileType::Account, path)]);
+
+    // negative tests
+    let _ = check_files_ref(&[(FileType::Account, path)]);
+    let _ = check_files_mut(&[(FileType::Account, path)]);
+    let _ = check_files_ref_mut(&[(FileType::Account, path)]);
+    let _ = check_files_self_and_arg(&[(FileType::Account, path)]);
+    let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]);
+}
+
+// `check_files` and its variants are based on:
+// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
+fn check_files(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (t, path) in files.iter().copied() {
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_vec(files: Vec<(FileType, &std::path::Path)>) -> bool {
+    for (t, path) in files.iter().copied() {
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_ref(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (ref t, path) in files.iter().copied() {
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+#[allow(unused_assignments)]
+fn check_files_mut(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (mut t, path) in files.iter().copied() {
+        t = FileType::PrivateKey;
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_ref_mut(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (ref mut t, path) in files.iter().copied() {
+        *t = FileType::PrivateKey;
+        let other = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn check_files_self_and_arg(files: &[(FileType, &std::path::Path)]) -> bool {
+    for (t, path) in files.iter().copied() {
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.join(path).is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+#[allow(unused_assignments)]
+fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool {
+    for (mut t, path) in files.iter().cloned() {
+        t = FileType::PrivateKey;
+        let other = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() || !other.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
+    Ok(std::path::PathBuf::new())
+}
diff --git a/tests/ui/unnecessary_iter_cloned.stderr b/tests/ui/unnecessary_iter_cloned.stderr
new file mode 100644
index 00000000000..e44379f8aa0
--- /dev/null
+++ b/tests/ui/unnecessary_iter_cloned.stderr
@@ -0,0 +1,35 @@
+error: unnecessary use of `copied`
+  --> $DIR/unnecessary_iter_cloned.rs:31:22
+   |
+LL |     for (t, path) in files.iter().copied() {
+   |                      ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::unnecessary-to-owned` implied by `-D warnings`
+help: use
+   |
+LL |     for (t, path) in files {
+   |                      ~~~~~
+help: remove this `&`
+   |
+LL -         let other = match get_file_path(&t) {
+LL +         let other = match get_file_path(t) {
+   | 
+
+error: unnecessary use of `copied`
+  --> $DIR/unnecessary_iter_cloned.rs:46:22
+   |
+LL |     for (t, path) in files.iter().copied() {
+   |                      ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL |     for (t, path) in files.iter() {
+   |                      ~~~~~~~~~~~~
+help: remove this `&`
+   |
+LL -         let other = match get_file_path(&t) {
+LL +         let other = match get_file_path(t) {
+   | 
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed
index bd9ef1fff42..720138db137 100644
--- a/tests/ui/unnecessary_to_owned.fixed
+++ b/tests/ui/unnecessary_to_owned.fixed
@@ -1,10 +1,6 @@
 // run-rustfix
 
 #![allow(clippy::ptr_arg)]
-// `needless_borrow` is to ensure there are no needles borrows in the fixed code.
-#![warn(clippy::needless_borrow)]
-// `redundant_clone` is to ensure there is no overlap between that lint and this one.
-#![warn(clippy::redundant_clone)]
 #![warn(clippy::unnecessary_to_owned)]
 
 use std::borrow::Cow;
@@ -41,6 +37,14 @@ impl X {
     }
 }
 
+#[allow(dead_code)]
+#[derive(Clone)]
+enum FileType {
+    Account,
+    PrivateKey,
+    Certificate,
+}
+
 fn main() {
     let c_str = CStr::from_bytes_with_nul(&[0]).unwrap();
     let os_str = OsStr::new("x");
@@ -120,6 +124,18 @@ fn main() {
 
     let _ = x.join(x_ref);
 
+    let _ = slice.iter().copied();
+    let _ = slice.iter().copied();
+    let _ = [std::path::PathBuf::new()][..].iter().cloned();
+    let _ = [std::path::PathBuf::new()][..].iter().cloned();
+
+    let _ = slice.iter().copied();
+    let _ = slice.iter().copied();
+    let _ = [std::path::PathBuf::new()][..].iter().cloned();
+    let _ = [std::path::PathBuf::new()][..].iter().cloned();
+
+    let _ = check_files(&[FileType::Account]);
+
     // negative tests
     require_string(&s.to_string());
     require_string(&Cow::from(s).into_owned());
@@ -174,4 +190,25 @@ fn require_impl_as_ref_slice<T>(_: impl AsRef<[T]>) {}
 fn require_as_ref_str_slice<T: AsRef<str>, U, V: AsRef<[U]>>(_: T, _: V) {}
 fn require_as_ref_slice_str<T, U: AsRef<[T]>, V: AsRef<str>>(_: U, _: V) {}
 
+// `check_files` is based on:
+// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
+fn check_files(file_types: &[FileType]) -> bool {
+    for t in file_types {
+        let path = match get_file_path(t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
+    Ok(std::path::PathBuf::new())
+}
+
 fn require_string(_: &String) {}
diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs
index 1bf30e22893..60b2e718f5d 100644
--- a/tests/ui/unnecessary_to_owned.rs
+++ b/tests/ui/unnecessary_to_owned.rs
@@ -1,10 +1,6 @@
 // run-rustfix
 
 #![allow(clippy::ptr_arg)]
-// `needless_borrow` is to ensure there are no needles borrows in the fixed code.
-#![warn(clippy::needless_borrow)]
-// `redundant_clone` is to ensure there is no overlap between that lint and this one.
-#![warn(clippy::redundant_clone)]
 #![warn(clippy::unnecessary_to_owned)]
 
 use std::borrow::Cow;
@@ -41,6 +37,14 @@ impl X {
     }
 }
 
+#[allow(dead_code)]
+#[derive(Clone)]
+enum FileType {
+    Account,
+    PrivateKey,
+    Certificate,
+}
+
 fn main() {
     let c_str = CStr::from_bytes_with_nul(&[0]).unwrap();
     let os_str = OsStr::new("x");
@@ -120,6 +124,18 @@ fn main() {
 
     let _ = x.join(&x_ref.to_string());
 
+    let _ = slice.to_vec().into_iter();
+    let _ = slice.to_owned().into_iter();
+    let _ = [std::path::PathBuf::new()][..].to_vec().into_iter();
+    let _ = [std::path::PathBuf::new()][..].to_owned().into_iter();
+
+    let _ = IntoIterator::into_iter(slice.to_vec());
+    let _ = IntoIterator::into_iter(slice.to_owned());
+    let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec());
+    let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned());
+
+    let _ = check_files(&[FileType::Account]);
+
     // negative tests
     require_string(&s.to_string());
     require_string(&Cow::from(s).into_owned());
@@ -174,4 +190,25 @@ fn require_impl_as_ref_slice<T>(_: impl AsRef<[T]>) {}
 fn require_as_ref_str_slice<T: AsRef<str>, U, V: AsRef<[U]>>(_: T, _: V) {}
 fn require_as_ref_slice_str<T, U: AsRef<[T]>, V: AsRef<str>>(_: U, _: V) {}
 
+// `check_files` is based on:
+// https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262
+fn check_files(file_types: &[FileType]) -> bool {
+    for t in file_types.to_vec() {
+        let path = match get_file_path(&t) {
+            Ok(p) => p,
+            Err(_) => {
+                return false;
+            },
+        };
+        if !path.is_file() {
+            return false;
+        }
+    }
+    true
+}
+
+fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::Error> {
+    Ok(std::path::PathBuf::new())
+}
+
 fn require_string(_: &String) {}
diff --git a/tests/ui/unnecessary_to_owned.stderr b/tests/ui/unnecessary_to_owned.stderr
index 83cc53ef3a2..1dfc65e22e2 100644
--- a/tests/ui/unnecessary_to_owned.stderr
+++ b/tests/ui/unnecessary_to_owned.stderr
@@ -1,54 +1,54 @@
 error: redundant clone
-  --> $DIR/unnecessary_to_owned.rs:134:64
+  --> $DIR/unnecessary_to_owned.rs:150:64
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                                                                ^^^^^^^^^^^ help: remove this
    |
    = note: `-D clippy::redundant-clone` implied by `-D warnings`
 note: this value is dropped without further use
-  --> $DIR/unnecessary_to_owned.rs:134:20
+  --> $DIR/unnecessary_to_owned.rs:150:20
    |
 LL |     require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/unnecessary_to_owned.rs:135:40
+  --> $DIR/unnecessary_to_owned.rs:151:40
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                                        ^^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/unnecessary_to_owned.rs:135:21
+  --> $DIR/unnecessary_to_owned.rs:151:21
    |
 LL |     require_os_str(&OsString::from("x").to_os_string());
    |                     ^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/unnecessary_to_owned.rs:136:48
+  --> $DIR/unnecessary_to_owned.rs:152:48
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                                                ^^^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/unnecessary_to_owned.rs:136:19
+  --> $DIR/unnecessary_to_owned.rs:152:19
    |
 LL |     require_path(&std::path::PathBuf::from("x").to_path_buf());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: redundant clone
-  --> $DIR/unnecessary_to_owned.rs:137:35
+  --> $DIR/unnecessary_to_owned.rs:153:35
    |
 LL |     require_str(&String::from("x").to_string());
    |                                   ^^^^^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/unnecessary_to_owned.rs:137:18
+  --> $DIR/unnecessary_to_owned.rs:153:18
    |
 LL |     require_str(&String::from("x").to_string());
    |                  ^^^^^^^^^^^^^^^^^
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:55:36
+  --> $DIR/unnecessary_to_owned.rs:59:36
    |
 LL |     require_c_str(&Cow::from(c_str).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
@@ -56,376 +56,440 @@ LL |     require_c_str(&Cow::from(c_str).into_owned());
    = note: `-D clippy::unnecessary-to-owned` implied by `-D warnings`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:56:19
+  --> $DIR/unnecessary_to_owned.rs:60:19
    |
 LL |     require_c_str(&c_str.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_os_string`
-  --> $DIR/unnecessary_to_owned.rs:58:20
+  --> $DIR/unnecessary_to_owned.rs:62:20
    |
 LL |     require_os_str(&os_str.to_os_string());
    |                    ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:59:38
+  --> $DIR/unnecessary_to_owned.rs:63:38
    |
 LL |     require_os_str(&Cow::from(os_str).into_owned());
    |                                      ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:60:20
+  --> $DIR/unnecessary_to_owned.rs:64:20
    |
 LL |     require_os_str(&os_str.to_owned());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_path_buf`
-  --> $DIR/unnecessary_to_owned.rs:62:18
+  --> $DIR/unnecessary_to_owned.rs:66:18
    |
 LL |     require_path(&path.to_path_buf());
    |                  ^^^^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:63:34
+  --> $DIR/unnecessary_to_owned.rs:67:34
    |
 LL |     require_path(&Cow::from(path).into_owned());
    |                                  ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:64:18
+  --> $DIR/unnecessary_to_owned.rs:68:18
    |
 LL |     require_path(&path.to_owned());
    |                  ^^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_string`
-  --> $DIR/unnecessary_to_owned.rs:66:17
+  --> $DIR/unnecessary_to_owned.rs:70:17
    |
 LL |     require_str(&s.to_string());
    |                 ^^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:67:30
+  --> $DIR/unnecessary_to_owned.rs:71:30
    |
 LL |     require_str(&Cow::from(s).into_owned());
    |                              ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:68:17
+  --> $DIR/unnecessary_to_owned.rs:72:17
    |
 LL |     require_str(&s.to_owned());
    |                 ^^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> $DIR/unnecessary_to_owned.rs:69:17
+  --> $DIR/unnecessary_to_owned.rs:73:17
    |
 LL |     require_str(&x_ref.to_string());
    |                 ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()`
 
 error: unnecessary use of `to_vec`
-  --> $DIR/unnecessary_to_owned.rs:71:19
+  --> $DIR/unnecessary_to_owned.rs:75:19
    |
 LL |     require_slice(&slice.to_vec());
    |                   ^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:72:36
+  --> $DIR/unnecessary_to_owned.rs:76:36
    |
 LL |     require_slice(&Cow::from(slice).into_owned());
    |                                    ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:73:19
+  --> $DIR/unnecessary_to_owned.rs:77:19
    |
 LL |     require_slice(&array.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:74:19
+  --> $DIR/unnecessary_to_owned.rs:78:19
    |
 LL |     require_slice(&array_ref.to_owned());
    |                   ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:75:19
+  --> $DIR/unnecessary_to_owned.rs:79:19
    |
 LL |     require_slice(&slice.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:76:19
+  --> $DIR/unnecessary_to_owned.rs:80:19
    |
 LL |     require_slice(&x_ref.to_owned());
    |                   ^^^^^^^^^^^^^^^^^ help: use: `x_ref`
 
 error: unnecessary use of `into_owned`
-  --> $DIR/unnecessary_to_owned.rs:78:42
+  --> $DIR/unnecessary_to_owned.rs:82:42
    |
 LL |     require_x(&Cow::<X>::Owned(x.clone()).into_owned());
    |                                          ^^^^^^^^^^^^^ help: remove this
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:79:15
+  --> $DIR/unnecessary_to_owned.rs:83:15
    |
 LL |     require_x(&x_ref.to_owned());
    |               ^^^^^^^^^^^^^^^^^ help: use: `x_ref`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:81:25
+  --> $DIR/unnecessary_to_owned.rs:85:25
    |
 LL |     require_deref_c_str(c_str.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:82:26
+  --> $DIR/unnecessary_to_owned.rs:86:26
    |
 LL |     require_deref_os_str(os_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:83:24
+  --> $DIR/unnecessary_to_owned.rs:87:24
    |
 LL |     require_deref_path(path.to_owned());
    |                        ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:84:23
+  --> $DIR/unnecessary_to_owned.rs:88:23
    |
 LL |     require_deref_str(s.to_owned());
    |                       ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:85:25
+  --> $DIR/unnecessary_to_owned.rs:89:25
    |
 LL |     require_deref_slice(slice.to_owned());
    |                         ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:87:30
+  --> $DIR/unnecessary_to_owned.rs:91:30
    |
 LL |     require_impl_deref_c_str(c_str.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:88:31
+  --> $DIR/unnecessary_to_owned.rs:92:31
    |
 LL |     require_impl_deref_os_str(os_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:89:29
+  --> $DIR/unnecessary_to_owned.rs:93:29
    |
 LL |     require_impl_deref_path(path.to_owned());
    |                             ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:90:28
+  --> $DIR/unnecessary_to_owned.rs:94:28
    |
 LL |     require_impl_deref_str(s.to_owned());
    |                            ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:91:30
+  --> $DIR/unnecessary_to_owned.rs:95:30
    |
 LL |     require_impl_deref_slice(slice.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:93:29
+  --> $DIR/unnecessary_to_owned.rs:97:29
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:93:43
+  --> $DIR/unnecessary_to_owned.rs:97:43
    |
 LL |     require_deref_str_slice(s.to_owned(), slice.to_owned());
    |                                           ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:94:29
+  --> $DIR/unnecessary_to_owned.rs:98:29
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                             ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:94:47
+  --> $DIR/unnecessary_to_owned.rs:98:47
    |
 LL |     require_deref_slice_str(slice.to_owned(), s.to_owned());
    |                                               ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:96:26
+  --> $DIR/unnecessary_to_owned.rs:100:26
    |
 LL |     require_as_ref_c_str(c_str.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:97:27
+  --> $DIR/unnecessary_to_owned.rs:101:27
    |
 LL |     require_as_ref_os_str(os_str.to_owned());
    |                           ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:98:25
+  --> $DIR/unnecessary_to_owned.rs:102:25
    |
 LL |     require_as_ref_path(path.to_owned());
    |                         ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:99:24
+  --> $DIR/unnecessary_to_owned.rs:103:24
    |
 LL |     require_as_ref_str(s.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:100:24
+  --> $DIR/unnecessary_to_owned.rs:104:24
    |
 LL |     require_as_ref_str(x.to_owned());
    |                        ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:101:26
+  --> $DIR/unnecessary_to_owned.rs:105:26
    |
 LL |     require_as_ref_slice(array.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:102:26
+  --> $DIR/unnecessary_to_owned.rs:106:26
    |
 LL |     require_as_ref_slice(array_ref.to_owned());
    |                          ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:103:26
+  --> $DIR/unnecessary_to_owned.rs:107:26
    |
 LL |     require_as_ref_slice(slice.to_owned());
    |                          ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:105:31
+  --> $DIR/unnecessary_to_owned.rs:109:31
    |
 LL |     require_impl_as_ref_c_str(c_str.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `c_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:106:32
+  --> $DIR/unnecessary_to_owned.rs:110:32
    |
 LL |     require_impl_as_ref_os_str(os_str.to_owned());
    |                                ^^^^^^^^^^^^^^^^^ help: use: `os_str`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:107:30
+  --> $DIR/unnecessary_to_owned.rs:111:30
    |
 LL |     require_impl_as_ref_path(path.to_owned());
    |                              ^^^^^^^^^^^^^^^ help: use: `path`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:108:29
+  --> $DIR/unnecessary_to_owned.rs:112:29
    |
 LL |     require_impl_as_ref_str(s.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:109:29
+  --> $DIR/unnecessary_to_owned.rs:113:29
    |
 LL |     require_impl_as_ref_str(x.to_owned());
    |                             ^^^^^^^^^^^^ help: use: `&x`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:110:31
+  --> $DIR/unnecessary_to_owned.rs:114:31
    |
 LL |     require_impl_as_ref_slice(array.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:111:31
+  --> $DIR/unnecessary_to_owned.rs:115:31
    |
 LL |     require_impl_as_ref_slice(array_ref.to_owned());
    |                               ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:112:31
+  --> $DIR/unnecessary_to_owned.rs:116:31
    |
 LL |     require_impl_as_ref_slice(slice.to_owned());
    |                               ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:114:30
+  --> $DIR/unnecessary_to_owned.rs:118:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:114:44
+  --> $DIR/unnecessary_to_owned.rs:118:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:115:30
+  --> $DIR/unnecessary_to_owned.rs:119:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:115:44
+  --> $DIR/unnecessary_to_owned.rs:119:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), array_ref.to_owned());
    |                                            ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:116:30
+  --> $DIR/unnecessary_to_owned.rs:120:30
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                              ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:116:44
+  --> $DIR/unnecessary_to_owned.rs:120:44
    |
 LL |     require_as_ref_str_slice(s.to_owned(), slice.to_owned());
    |                                            ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:117:30
+  --> $DIR/unnecessary_to_owned.rs:121:30
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `array`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:117:48
+  --> $DIR/unnecessary_to_owned.rs:121:48
    |
 LL |     require_as_ref_slice_str(array.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:118:30
+  --> $DIR/unnecessary_to_owned.rs:122:30
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:118:52
+  --> $DIR/unnecessary_to_owned.rs:122:52
    |
 LL |     require_as_ref_slice_str(array_ref.to_owned(), s.to_owned());
    |                                                    ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:119:30
+  --> $DIR/unnecessary_to_owned.rs:123:30
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                              ^^^^^^^^^^^^^^^^ help: use: `slice`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned.rs:119:48
+  --> $DIR/unnecessary_to_owned.rs:123:48
    |
 LL |     require_as_ref_slice_str(slice.to_owned(), s.to_owned());
    |                                                ^^^^^^^^^^^^ help: use: `s`
 
 error: unnecessary use of `to_string`
-  --> $DIR/unnecessary_to_owned.rs:121:20
+  --> $DIR/unnecessary_to_owned.rs:125:20
    |
 LL |     let _ = x.join(&x_ref.to_string());
    |                    ^^^^^^^^^^^^^^^^^^ help: use: `x_ref`
 
-error: aborting due to 67 previous errors
+error: unnecessary use of `to_vec`
+  --> $DIR/unnecessary_to_owned.rs:127:13
+   |
+LL |     let _ = slice.to_vec().into_iter();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
+
+error: unnecessary use of `to_owned`
+  --> $DIR/unnecessary_to_owned.rs:128:13
+   |
+LL |     let _ = slice.to_owned().into_iter();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
+
+error: unnecessary use of `to_vec`
+  --> $DIR/unnecessary_to_owned.rs:129:13
+   |
+LL |     let _ = [std::path::PathBuf::new()][..].to_vec().into_iter();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
+
+error: unnecessary use of `to_owned`
+  --> $DIR/unnecessary_to_owned.rs:130:13
+   |
+LL |     let _ = [std::path::PathBuf::new()][..].to_owned().into_iter();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
+
+error: unnecessary use of `to_vec`
+  --> $DIR/unnecessary_to_owned.rs:132:13
+   |
+LL |     let _ = IntoIterator::into_iter(slice.to_vec());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
+
+error: unnecessary use of `to_owned`
+  --> $DIR/unnecessary_to_owned.rs:133:13
+   |
+LL |     let _ = IntoIterator::into_iter(slice.to_owned());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()`
+
+error: unnecessary use of `to_vec`
+  --> $DIR/unnecessary_to_owned.rs:134:13
+   |
+LL |     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
+
+error: unnecessary use of `to_owned`
+  --> $DIR/unnecessary_to_owned.rs:135:13
+   |
+LL |     let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()`
+
+error: unnecessary use of `to_vec`
+  --> $DIR/unnecessary_to_owned.rs:196:14
+   |
+LL |     for t in file_types.to_vec() {
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+help: use
+   |
+LL |     for t in file_types {
+   |              ~~~~~~~~~~
+help: remove this `&`
+   |
+LL -         let path = match get_file_path(&t) {
+LL +         let path = match get_file_path(t) {
+   | 
+
+error: aborting due to 76 previous errors