11use clippy_utils:: diagnostics:: { span_lint, span_lint_and_then} ;
2- use clippy_utils:: macros:: { root_macro_call_first_node, FormatArgsExpn , MacroCall } ;
2+ use clippy_utils:: macros:: { root_macro_call_first_node, FormatArgsArg , FormatArgsExpn , MacroCall } ;
33use clippy_utils:: source:: snippet_opt;
44use rustc_ast:: LitKind ;
55use rustc_errors:: Applicability ;
@@ -275,6 +275,9 @@ impl<'tcx> LateLintPass<'tcx> for Write {
275275 }
276276
277277 let Some ( format_args) = FormatArgsExpn :: find_nested ( cx, expr, macro_call. expn ) else { return } ;
278+ if format_args. format_string_span . from_expansion ( ) {
279+ return ;
280+ }
278281
279282 match diag_name {
280283 sym:: print_macro | sym:: eprint_macro | sym:: write_macro => {
@@ -286,20 +289,15 @@ impl<'tcx> LateLintPass<'tcx> for Write {
286289 _ => { } ,
287290 }
288291
289- check_literal ( cx, & format_args, name) ;
292+ let Some ( args) = format_args. args ( cx) else { return } ;
293+ check_literal ( cx, & args, name, format_args. is_raw ( cx) ) ;
290294
291- if !self . in_debug_impl
292- && format_args
293- . formatters
294- . iter ( )
295- . any ( |& ( _, formatter) | formatter == sym:: Debug )
296- {
297- span_lint (
298- cx,
299- USE_DEBUG ,
300- format_args. format_string_span ,
301- "use of `Debug`-based formatting" ,
302- ) ;
295+ if !self . in_debug_impl {
296+ for arg in args {
297+ if arg. format_trait == sym:: Debug {
298+ span_lint ( cx, USE_DEBUG , arg. span , "use of `Debug`-based formatting" ) ;
299+ }
300+ }
303301 }
304302 }
305303}
@@ -335,7 +333,6 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c
335333 } ;
336334
337335 if_chain ! {
338- if !format_string_span. from_expansion( ) ;
339336 if last. as_str( ) . ends_with( '\n' ) ;
340337
341338 // ignore format strings with other internal vertical whitespace
@@ -401,9 +398,6 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
401398 let mut span = format_args. format_string_span;
402399
403400 if part. as_str( ) == "\n " ;
404- // `println!()` is also represented with an "\n" format string part, but
405- // its span is from an expansion
406- if !span. from_expansion( ) ;
407401 then {
408402 let lint = if name == "writeln" {
409403 span = expand_past_previous_comma( cx, span) ;
@@ -432,15 +426,9 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
432426 }
433427}
434428
435- fn check_literal < ' tcx > ( cx : & LateContext < ' tcx > , format_args : & FormatArgsExpn < ' tcx > , name : & str ) {
436- if format_args. format_string_span . from_expansion ( ) {
437- return ;
438- }
439- let raw = format_args. is_raw ( cx) ;
440-
441- let Some ( args) = format_args. args ( cx) else { return } ;
429+ fn check_literal ( cx : & LateContext < ' _ > , args : & [ FormatArgsArg < ' _ > ] , name : & str , raw : bool ) {
442430 let mut counts = HirIdMap :: < usize > :: default ( ) ;
443- for arg in & args {
431+ for arg in args {
444432 * counts. entry ( arg. value . hir_id ) . or_default ( ) += 1 ;
445433 }
446434
0 commit comments