about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-15 10:01:20 +0000
committerbors <bors@rust-lang.org>2022-08-15 10:01:20 +0000
commit8c9040ceaa7ee32e77c8e8eb8002087accb13a38 (patch)
tree08f80e6d0e9941c50d44bae19bfc4f8acb84737a
parent679fa9f2bfbdb65f0eb7732fa20043fd0f6813a8 (diff)
parent1a2aaf68de4989eaacf5b669da00b50dca8b41e0 (diff)
downloadrust-8c9040ceaa7ee32e77c8e8eb8002087accb13a38.tar.gz
rust-8c9040ceaa7ee32e77c8e8eb8002087accb13a38.zip
Auto merge of #9329 - xphoniex:fix-#9317, r=flip1995
Skip `unnecessary_to_owned` when `t != t.to_string()`

Fixes #9317

changelog: [`unnecessary_to_owned`]: none
-rw-r--r--clippy_lints/src/methods/unnecessary_to_owned.rs17
-rw-r--r--tests/ui/unnecessary_to_owned.fixed28
-rw-r--r--tests/ui/unnecessary_to_owned.rs28
3 files changed, 71 insertions, 2 deletions
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs
index b3276f1394e..99b56da7a50 100644
--- a/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -3,7 +3,8 @@ 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::{
-    contains_ty, get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs,
+    contains_ty, get_associated_type, get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item,
+    peel_mid_ty_refs,
 };
 use clippy_utils::{meets_msrv, msrvs};
 
@@ -279,7 +280,19 @@ fn check_other_call_arg<'tcx>(
                 &trait_predicate.trait_ref.substs.iter().skip(1).collect::<Vec<_>>()[..],
                 call_substs,
             );
-            implements_trait(cx, receiver_ty, as_ref_trait_id, &composed_substs)
+            // if `expr` is a `String` and generic target is [u8], skip
+            // (https://github.com/rust-lang/rust-clippy/issues/9317).
+            if let [subst] = composed_substs[..]
+                && let GenericArgKind::Type(arg_ty) = subst.unpack()
+                && arg_ty.is_slice()
+                && let inner_ty = arg_ty.builtin_index().unwrap()
+                && let ty::Uint(ty::UintTy::U8) = inner_ty.kind()
+                && let self_ty = cx.typeck_results().expr_ty(expr).peel_refs()
+                && is_type_diagnostic_item(cx, self_ty, sym::String) {
+                false
+            } else {
+                implements_trait(cx, receiver_ty, as_ref_trait_id, &composed_substs)
+            }
         } else {
             false
         };
diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed
index f4f76cd3dd4..9cd5bc73b1e 100644
--- a/tests/ui/unnecessary_to_owned.fixed
+++ b/tests/ui/unnecessary_to_owned.fixed
@@ -329,3 +329,31 @@ mod issue_8759_variant {
         rw.set_view(&rw.default_view().to_owned());
     }
 }
+
+mod issue_9317 {
+    #![allow(dead_code)]
+
+    struct Bytes {}
+
+    impl ToString for Bytes {
+        fn to_string(&self) -> String {
+            "123".to_string()
+        }
+    }
+
+    impl AsRef<[u8]> for Bytes {
+        fn as_ref(&self) -> &[u8] {
+            &[1, 2, 3]
+        }
+    }
+
+    fn consume<C: AsRef<[u8]>>(c: C) {
+        let _ = c;
+    }
+
+    pub fn main() {
+        let b = Bytes {};
+        // Should not lint.
+        consume(b.to_string());
+    }
+}
diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs
index fe09a489ab0..7f62ba3ab5d 100644
--- a/tests/ui/unnecessary_to_owned.rs
+++ b/tests/ui/unnecessary_to_owned.rs
@@ -329,3 +329,31 @@ mod issue_8759_variant {
         rw.set_view(&rw.default_view().to_owned());
     }
 }
+
+mod issue_9317 {
+    #![allow(dead_code)]
+
+    struct Bytes {}
+
+    impl ToString for Bytes {
+        fn to_string(&self) -> String {
+            "123".to_string()
+        }
+    }
+
+    impl AsRef<[u8]> for Bytes {
+        fn as_ref(&self) -> &[u8] {
+            &[1, 2, 3]
+        }
+    }
+
+    fn consume<C: AsRef<[u8]>>(c: C) {
+        let _ = c;
+    }
+
+    pub fn main() {
+        let b = Bytes {};
+        // Should not lint.
+        consume(b.to_string());
+    }
+}