about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-09 08:52:44 +0000
committerbors <bors@rust-lang.org>2023-06-09 08:52:44 +0000
commit05de7870899f43d67add6c00aec33e23e2d4c09c (patch)
treef418cabf959615a0ccbed4753860c0ef6982431d /tests
parent384cf376120f09df7710d2ff39c986144a7b1517 (diff)
parentdd084940de3947b7d095fcbd6d3381f98470c58b (diff)
downloadrust-05de7870899f43d67add6c00aec33e23e2d4c09c.tar.gz
rust-05de7870899f43d67add6c00aec33e23e2d4c09c.zip
Auto merge of #10913 - y21:issue10033, r=Manishearth,Centri3
[`unnecessary_to_owned`]: check that the adjusted type matches target

Fixes #10033.

Before this change, the lint would assume that removing the `.to_string()` in `f(&x.to_string())` would be ok if x is of some type that implements `Deref<Target = str>` and `f` takes a `&str`.
This turns out to not actually be ok if the `to_string` call is some method that exists on `x` directly, which happens if it implements `Display`/`ToString` itself.

changelog: [`unnecessary_to_owned`]: only lint if the adjusted receiver type actually matches
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/unnecessary_to_owned.fixed33
-rw-r--r--tests/ui/unnecessary_to_owned.rs33
2 files changed, 66 insertions, 0 deletions
diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed
index 08733906b0e..592a53f3a81 100644
--- a/tests/ui/unnecessary_to_owned.fixed
+++ b/tests/ui/unnecessary_to_owned.fixed
@@ -474,3 +474,36 @@ mod issue_10021 {
         Ok(())
     }
 }
+
+mod issue_10033 {
+    #![allow(dead_code)]
+    use std::{fmt::Display, ops::Deref};
+
+    fn _main() {
+        let f = Foo;
+
+        // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
+        // deref to `str`)
+        foo(&f.to_string());
+    }
+
+    fn foo(s: &str) {
+        println!("{}", s);
+    }
+
+    struct Foo;
+
+    impl Deref for Foo {
+        type Target = str;
+
+        fn deref(&self) -> &Self::Target {
+            "str"
+        }
+    }
+
+    impl Display for Foo {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "Foo")
+        }
+    }
+}
diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs
index e3589ea0d65..f2e48b1c4a6 100644
--- a/tests/ui/unnecessary_to_owned.rs
+++ b/tests/ui/unnecessary_to_owned.rs
@@ -474,3 +474,36 @@ mod issue_10021 {
         Ok(())
     }
 }
+
+mod issue_10033 {
+    #![allow(dead_code)]
+    use std::{fmt::Display, ops::Deref};
+
+    fn _main() {
+        let f = Foo;
+
+        // Not actually unnecessary - this calls `Foo`'s `Display` impl, not `str`'s (even though `Foo` does
+        // deref to `str`)
+        foo(&f.to_string());
+    }
+
+    fn foo(s: &str) {
+        println!("{}", s);
+    }
+
+    struct Foo;
+
+    impl Deref for Foo {
+        type Target = str;
+
+        fn deref(&self) -> &Self::Target {
+            "str"
+        }
+    }
+
+    impl Display for Foo {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "Foo")
+        }
+    }
+}