use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; declare_clippy_lint! { /// ### What it does /// Checks for direct implementations of `ToString`. /// ### Why is this bad? /// This trait is automatically implemented for any type which implements the `Display` trait. /// As such, `ToString` shouldn’t be implemented directly: `Display` should be implemented instead, /// and you get the `ToString` implementation for free. /// ### Example /// ```no_run /// struct Point { /// x: usize, /// y: usize, /// } /// /// impl ToString for Point { /// fn to_string(&self) -> String { /// format!("({}, {})", self.x, self.y) /// } /// } /// ``` /// Use instead: /// ```no_run /// struct Point { /// x: usize, /// y: usize, /// } /// /// impl std::fmt::Display for Point { /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// write!(f, "({}, {})", self.x, self.y) /// } /// } /// ``` #[clippy::version = "1.78.0"] pub TO_STRING_TRAIT_IMPL, style, "check for direct implementations of `ToString`" } declare_lint_pass!(ToStringTraitImpl => [TO_STRING_TRAIT_IMPL]); impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'tcx>) { if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = it.kind && let Some(trait_did) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::ToString, trait_did) { span_lint_and_help( cx, TO_STRING_TRAIT_IMPL, it.span, "direct implementation of `ToString`", None, "prefer implementing `Display` instead", ); } } }