diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index f800516b7ced..8b27442aa946 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -153,14 +153,12 @@ fn check_to_string_in_format_args<'tcx>(cx: &LateContext<'tcx>, name: Symbol, ar if let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display); if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); then { - let (n_overloaded_derefs, target) = count_overloaded_derefs( - 0, - 0, + let (n_needed_derefs, target) = count_needed_derefs( receiver_ty, - &mut cx.typeck_results().expr_adjustments(receiver).iter(), + cx.typeck_results().expr_adjustments(receiver).iter(), ); if implements_trait(cx, target, display_trait_id, &[]) { - if n_overloaded_derefs == 0 { + if n_needed_derefs == 0 { span_lint_and_sugg( cx, TO_STRING_IN_FORMAT_ARGS, @@ -177,7 +175,7 @@ fn check_to_string_in_format_args<'tcx>(cx: &LateContext<'tcx>, name: Symbol, ar value.span, &format!("`to_string` applied to a type that implements `Display` in `{}!` args", name), "use this", - format!("{:*>width$}{}", "", receiver_snippet, width = n_overloaded_derefs), + format!("{:*>width$}{}", "", receiver_snippet, width = n_needed_derefs), Applicability::MachineApplicable, ); } @@ -201,31 +199,25 @@ fn trim_semicolon(cx: &LateContext<'_>, span: Span) -> Span { }) } -fn count_overloaded_derefs<'tcx, I>( - n_total: usize, - n_overloaded: usize, - ty: Ty<'tcx>, - iter: &mut I, -) -> (usize, Ty<'tcx>) +fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>) where I: Iterator>, { - if let Some(Adjustment { - kind: Adjust::Deref(overloaded_deref), - target, - }) = iter.next() - { - count_overloaded_derefs( - n_total + 1, - if overloaded_deref.is_some() { - n_total + 1 - } else { - n_overloaded - }, + let mut n_total = 0; + let mut n_needed = 0; + loop { + if let Some(Adjustment { + kind: Adjust::Deref(overloaded_deref), target, - iter, - ) - } else { - (n_overloaded, ty) + }) = iter.next() + { + n_total += 1; + if overloaded_deref.is_some() { + n_needed = n_total; + } + ty = target; + } else { + return (n_needed, ty); + } } } diff --git a/tests/ui/format_args.fixed b/tests/ui/format_args.fixed index 77ebc9c10a97..8376566c4d62 100644 --- a/tests/ui/format_args.fixed +++ b/tests/ui/format_args.fixed @@ -69,7 +69,7 @@ macro_rules! my_other_macro { } fn main() { - let x = 'x'; + let x = &X(1); let x_ref = &x; let _ = format!("error: something failed at {}", Location::caller()); @@ -95,7 +95,8 @@ fn main() { println!("{}", *X(1)); println!("{}", ***Y(&X(1))); println!("{}", Z(1)); - println!("{}", x_ref); + println!("{}", **x); + println!("{}", ***x_ref); println!("error: something failed at {}", Somewhere.to_string()); println!("{} and again {0}", x.to_string()); diff --git a/tests/ui/format_args.rs b/tests/ui/format_args.rs index d495ac9edde5..164cc07066dc 100644 --- a/tests/ui/format_args.rs +++ b/tests/ui/format_args.rs @@ -69,7 +69,7 @@ macro_rules! my_other_macro { } fn main() { - let x = 'x'; + let x = &X(1); let x_ref = &x; let _ = format!("error: something failed at {}", Location::caller().to_string()); @@ -95,6 +95,7 @@ fn main() { println!("{}", X(1).to_string()); println!("{}", Y(&X(1)).to_string()); println!("{}", Z(1).to_string()); + println!("{}", x.to_string()); println!("{}", x_ref.to_string()); println!("error: something failed at {}", Somewhere.to_string()); diff --git a/tests/ui/format_args.stderr b/tests/ui/format_args.stderr index ab4035686cd7..9cfc97edeafb 100644 --- a/tests/ui/format_args.stderr +++ b/tests/ui/format_args.stderr @@ -91,10 +91,16 @@ LL | println!("{}", Z(1).to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:98:25 + --> $DIR/format_args.rs:98:20 + | +LL | println!("{}", x.to_string()); + | ^^^^^^^^^^^^^ help: use this: `**x` + +error: `to_string` applied to a type that implements `Display` in `println!` args + --> $DIR/format_args.rs:99:20 | LL | println!("{}", x_ref.to_string()); - | ^^^^^^^^^^^^ help: remove this + | ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref` -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors