Skip to content

Commit 07c5e9e

Browse files
committed
Auto merge of #5971 - giraffate:fix_fp_in_to_string_in_display, r=ebroto
Fix FP in `to_string_in_display` Don't emit a lint when `.to_string()` on anything that is not `self` Fix #5967 changelog: Fix FP in `to_string_in_display` when calling `.to_string()` on anything that is not `self`
2 parents dead45f + 04bff17 commit 07c5e9e

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

clippy_lints/src/to_string_in_display.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use crate::utils::{match_def_path, match_trait_method, paths, span_lint};
1+
use crate::utils::{match_def_path, match_trait_method, paths, qpath_res, span_lint};
22
use if_chain::if_chain;
3-
use rustc_hir::{Expr, ExprKind, Item, ItemKind};
3+
use rustc_hir::def::Res;
4+
use rustc_hir::{Expr, ExprKind, HirId, ImplItem, ImplItemKind, Item, ItemKind};
45
use rustc_lint::{LateContext, LateLintPass};
56
use rustc_session::{declare_tool_lint, impl_lint_pass};
67

@@ -45,11 +46,15 @@ declare_clippy_lint! {
4546
#[derive(Default)]
4647
pub struct ToStringInDisplay {
4748
in_display_impl: bool,
49+
self_hir_id: Option<HirId>,
4850
}
4951

5052
impl ToStringInDisplay {
5153
pub fn new() -> Self {
52-
Self { in_display_impl: false }
54+
Self {
55+
in_display_impl: false,
56+
self_hir_id: None,
57+
}
5358
}
5459
}
5560

@@ -65,16 +70,33 @@ impl LateLintPass<'_> for ToStringInDisplay {
6570
fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
6671
if is_display_impl(cx, item) {
6772
self.in_display_impl = false;
73+
self.self_hir_id = None;
74+
}
75+
}
76+
77+
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) {
78+
if_chain! {
79+
if self.in_display_impl;
80+
if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
81+
let body = cx.tcx.hir().body(*body_id);
82+
if !body.params.is_empty();
83+
then {
84+
let self_param = &body.params[0];
85+
self.self_hir_id = Some(self_param.pat.hir_id);
86+
}
6887
}
6988
}
7089

7190
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
7291
if_chain! {
73-
if let ExprKind::MethodCall(ref path, _, _, _) = expr.kind;
92+
if let ExprKind::MethodCall(ref path, _, args, _) = expr.kind;
7493
if path.ident.name == sym!(to_string);
7594
if match_trait_method(cx, expr, &paths::TO_STRING);
7695
if self.in_display_impl;
77-
96+
if let ExprKind::Path(ref qpath) = args[0].kind;
97+
if let Res::Local(hir_id) = qpath_res(cx, qpath, args[0].hir_id);
98+
if let Some(self_hir_id) = self.self_hir_id;
99+
if hir_id == self_hir_id;
78100
then {
79101
span_lint(
80102
cx,

tests/ui/to_string_in_display.rs

+14
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ impl fmt::Display for C {
4444
}
4545
}
4646

47+
enum D {
48+
E(String),
49+
F,
50+
}
51+
52+
impl std::fmt::Display for D {
53+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54+
match &self {
55+
Self::E(string) => write!(f, "E {}", string.to_string()),
56+
Self::F => write!(f, "F"),
57+
}
58+
}
59+
}
60+
4761
fn main() {
4862
let a = A;
4963
a.to_string();

0 commit comments

Comments
 (0)