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,11 @@ 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+ check_use_debug ( cx, & args) ;
303297 }
304298 }
305299}
@@ -335,7 +329,6 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c
335329 } ;
336330
337331 if_chain ! {
338- if !format_string_span. from_expansion( ) ;
339332 if last. as_str( ) . ends_with( '\n' ) ;
340333
341334 // ignore format strings with other internal vertical whitespace
@@ -401,9 +394,6 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
401394 let mut span = format_args. format_string_span;
402395
403396 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( ) ;
407397 then {
408398 let lint = if name == "writeln" {
409399 span = expand_past_previous_comma( cx, span) ;
@@ -432,15 +422,9 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
432422 }
433423}
434424
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 } ;
425+ fn check_literal ( cx : & LateContext < ' _ > , args : & [ FormatArgsArg < ' _ > ] , name : & str , raw : bool ) {
442426 let mut counts = HirIdMap :: < usize > :: default ( ) ;
443- for arg in & args {
427+ for arg in args {
444428 * counts. entry ( arg. value . hir_id ) . or_default ( ) += 1 ;
445429 }
446430
@@ -505,3 +489,16 @@ fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
505489 let extended = cx. sess ( ) . source_map ( ) . span_extend_to_prev_char ( span, ',' , true ) ;
506490 extended. with_lo ( extended. lo ( ) - BytePos ( 1 ) )
507491}
492+
493+ fn check_use_debug ( cx : & LateContext < ' _ > , args : & [ FormatArgsArg < ' _ > ] ) {
494+ for arg in args {
495+ if arg. format_trait == sym:: Debug {
496+ span_lint (
497+ cx,
498+ USE_DEBUG ,
499+ arg. span ,
500+ "use of `Debug`-based formatting" ,
501+ ) ;
502+ }
503+ }
504+ }
0 commit comments