[to_string_trait_impl]: take specialization into account

This commit is contained in:
y21 2024-02-10 17:37:51 +01:00
parent 28443e63fb
commit b3b9919d1b
3 changed files with 61 additions and 2 deletions

View file

@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait;
use rustc_hir::{Impl, Item, ItemKind}; use rustc_hir::{Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
@ -53,6 +54,8 @@ impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl {
}) = it.kind }) = it.kind
&& let Some(trait_did) = trait_ref.trait_def_id() && let Some(trait_did) = trait_ref.trait_def_id()
&& cx.tcx.is_diagnostic_item(sym::ToString, trait_did) && 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( span_lint_and_help(
cx, cx,

View file

@ -1,4 +1,5 @@
#![warn(clippy::to_string_trait_impl)] #![warn(clippy::to_string_trait_impl)]
#![feature(min_specialization)]
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@ -29,3 +30,46 @@ impl Bar {
String::from("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!()
}
}
}

View file

@ -1,5 +1,5 @@
error: direct implementation of `ToString` 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 | / impl ToString for Point {
LL | | fn to_string(&self) -> String { LL | | fn to_string(&self) -> String {
@ -12,5 +12,17 @@ LL | | }
= note: `-D clippy::to-string-trait-impl` implied by `-D warnings` = note: `-D clippy::to-string-trait-impl` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::to_string_trait_impl)]` = 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