about summary refs log tree commit diff
diff options
context:
space:
mode:
authory21 <30553356+y21@users.noreply.github.com>2024-02-10 17:37:51 +0100
committery21 <30553356+y21@users.noreply.github.com>2024-02-10 17:37:51 +0100
commitb3b9919d1b4b321b0a9b7955ee06b9ecb755ce7e (patch)
treed5e285448b1ec57303bdc03b4cec812e877da16d
parent28443e63fb633a5ed00a49e8df591a956d77122c (diff)
downloadrust-b3b9919d1b4b321b0a9b7955ee06b9ecb755ce7e.tar.gz
rust-b3b9919d1b4b321b0a9b7955ee06b9ecb755ce7e.zip
[`to_string_trait_impl`]: take specialization into account
-rw-r--r--clippy_lints/src/to_string_trait_impl.rs3
-rw-r--r--tests/ui/to_string_trait_impl.rs44
-rw-r--r--tests/ui/to_string_trait_impl.stderr16
3 files changed, 61 insertions, 2 deletions
diff --git a/clippy_lints/src/to_string_trait_impl.rs b/clippy_lints/src/to_string_trait_impl.rs
index e1cea99085f..59ae185c9de 100644
--- a/clippy_lints/src/to_string_trait_impl.rs
+++ b/clippy_lints/src/to_string_trait_impl.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::implements_trait;
 use rustc_hir::{Impl, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -53,6 +54,8 @@ impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl {
         }) = it.kind
             && let Some(trait_did) = trait_ref.trait_def_id()
             && cx.tcx.is_diagnostic_item(sym::ToString, trait_did)
+            && let Some(display_did) = cx.tcx.get_diagnostic_item(sym::Display)
+            && !implements_trait(cx, cx.tcx.type_of(it.owner_id).instantiate_identity(), display_did, &[])
         {
             span_lint_and_help(
                 cx,
diff --git a/tests/ui/to_string_trait_impl.rs b/tests/ui/to_string_trait_impl.rs
index b0731632d45..4c1202d4203 100644
--- a/tests/ui/to_string_trait_impl.rs
+++ b/tests/ui/to_string_trait_impl.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::to_string_trait_impl)]
+#![feature(min_specialization)]
 
 use std::fmt::{self, Display};
 
@@ -29,3 +30,46 @@ impl Bar {
         String::from("Bar")
     }
 }
+
+mod issue12263 {
+    pub struct MyStringWrapper<'a>(&'a str);
+
+    impl std::fmt::Display for MyStringWrapper<'_> {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            self.0.fmt(f)
+        }
+    }
+
+    impl ToString for MyStringWrapper<'_> {
+        fn to_string(&self) -> String {
+            self.0.to_string()
+        }
+    }
+
+    pub struct S<T>(T);
+    impl std::fmt::Display for S<String> {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            todo!()
+        }
+    }
+    // no specialization if the generics differ, so lint
+    impl ToString for S<i32> {
+        fn to_string(&self) -> String {
+            todo!()
+        }
+    }
+
+    pub struct S2<T>(T);
+    impl std::fmt::Display for S2<String> {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            todo!()
+        }
+    }
+
+    // also specialization if the generics don't differ
+    impl ToString for S2<String> {
+        fn to_string(&self) -> String {
+            todo!()
+        }
+    }
+}
diff --git a/tests/ui/to_string_trait_impl.stderr b/tests/ui/to_string_trait_impl.stderr
index 55fa9f12c0e..0051ea25ae0 100644
--- a/tests/ui/to_string_trait_impl.stderr
+++ b/tests/ui/to_string_trait_impl.stderr
@@ -1,5 +1,5 @@
 error: direct implementation of `ToString`
-  --> $DIR/to_string_trait_impl.rs:10:1
+  --> $DIR/to_string_trait_impl.rs:11:1
    |
 LL | / impl ToString for Point {
 LL | |     fn to_string(&self) -> String {
@@ -12,5 +12,17 @@ LL | | }
    = note: `-D clippy::to-string-trait-impl` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::to_string_trait_impl)]`
 
-error: aborting due to 1 previous error
+error: direct implementation of `ToString`
+  --> $DIR/to_string_trait_impl.rs:56:5
+   |
+LL | /     impl ToString for S<i32> {
+LL | |         fn to_string(&self) -> String {
+LL | |             todo!()
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = help: prefer implementing `Display` instead
+
+error: aborting due to 2 previous errors