diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 8b921ce466aa..e3402d2e528d 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn, MacroCall}; +use clippy_utils::macros::{root_macro_call_first_node, FormatArgsArg, FormatArgsExpn, MacroCall}; use clippy_utils::source::snippet_opt; use rustc_ast::LitKind; use rustc_errors::Applicability; @@ -275,6 +275,9 @@ impl<'tcx> LateLintPass<'tcx> for Write { } let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn) else { return }; + if format_args.format_string_span.from_expansion() { + return; + } match diag_name { sym::print_macro | sym::eprint_macro | sym::write_macro => { @@ -286,20 +289,15 @@ impl<'tcx> LateLintPass<'tcx> for Write { _ => {}, } - check_literal(cx, &format_args, name); + let Some(args) = format_args.args(cx) else { return }; + check_literal(cx, &args, name, format_args.is_raw(cx)); - if !self.in_debug_impl - && format_args - .formatters - .iter() - .any(|&(_, formatter)| formatter == sym::Debug) - { - span_lint( - cx, - USE_DEBUG, - format_args.format_string_span, - "use of `Debug`-based formatting", - ); + if !self.in_debug_impl { + for arg in args { + if arg.format_trait == sym::Debug { + span_lint(cx, USE_DEBUG, arg.span, "use of `Debug`-based formatting"); + } + } } } } @@ -335,7 +333,6 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c }; if_chain! { - if !format_string_span.from_expansion(); if last.as_str().ends_with('\n'); // ignore format strings with other internal vertical whitespace @@ -401,9 +398,6 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma let mut span = format_args.format_string_span; if part.as_str() == "\n"; - // `println!()` is also represented with an "\n" format string part, but - // its span is from an expansion - if !span.from_expansion(); then { let lint = if name == "writeln" { span = expand_past_previous_comma(cx, span); @@ -432,15 +426,9 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma } } -fn check_literal<'tcx>(cx: &LateContext<'tcx>, format_args: &FormatArgsExpn<'tcx>, name: &str) { - if format_args.format_string_span.from_expansion() { - return; - } - let raw = format_args.is_raw(cx); - - let Some(args) = format_args.args(cx) else { return }; +fn check_literal(cx: &LateContext<'_>, args: &[FormatArgsArg<'_>], name: &str, raw: bool) { let mut counts = HirIdMap::::default(); - for arg in &args { + for arg in args { *counts.entry(arg.value.hir_id).or_default() += 1; } diff --git a/tests/ui/print.stderr b/tests/ui/print.stderr index 208d95326285..1754c418381a 100644 --- a/tests/ui/print.stderr +++ b/tests/ui/print.stderr @@ -1,8 +1,8 @@ error: use of `Debug`-based formatting - --> $DIR/print.rs:11:19 + --> $DIR/print.rs:11:20 | LL | write!(f, "{:?}", 43.1415) - | ^^^^^^ + | ^^^^ | = note: `-D clippy::use-debug` implied by `-D warnings` @@ -33,10 +33,10 @@ LL | print!("Hello {:?}", "World"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:28:12 + --> $DIR/print.rs:28:19 | LL | print!("Hello {:?}", "World"); - | ^^^^^^^^^^^^ + | ^^^^ error: use of `print!` --> $DIR/print.rs:30:5 @@ -45,10 +45,10 @@ LL | print!("Hello {:#?}", "#orld"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of `Debug`-based formatting - --> $DIR/print.rs:30:12 + --> $DIR/print.rs:30:19 | LL | print!("Hello {:#?}", "#orld"); - | ^^^^^^^^^^^^^ + | ^^^^^ error: aborting due to 8 previous errors