@@ -7,7 +7,7 @@ use syntax::ptr;
7
7
use syntax:: symbol:: InternedString ;
8
8
use syntax_pos:: Span ;
9
9
use utils:: { is_expn_of, match_def_path, match_path, resolve_node, span_lint, span_lint_and_sugg} ;
10
- use utils:: { opt_def_id, paths} ;
10
+ use utils:: { opt_def_id, paths, last_path_segment } ;
11
11
12
12
/// **What it does:** This lint warns when you use `println!("")` to
13
13
/// print a newline.
@@ -266,7 +266,6 @@ fn check_print_variants<'a, 'tcx>(
266
266
} ;
267
267
268
268
span_lint ( cx, PRINT_STDOUT , span, & format ! ( "use of `{}!`" , name) ) ;
269
-
270
269
if_chain ! {
271
270
// ensure we're calling Arguments::new_v1
272
271
if args. len( ) == 1 ;
@@ -339,7 +338,9 @@ where
339
338
F : Fn ( Span ) ,
340
339
{
341
340
if_chain ! {
342
- if args. len( ) > 1 ;
341
+ if args. len( ) >= 2 ;
342
+
343
+ // the match statement
343
344
if let ExprAddrOf ( _, ref match_expr) = args[ 1 ] . node;
344
345
if let ExprMatch ( ref matchee, ref arms, _) = match_expr. node;
345
346
if let ExprTup ( ref tup) = matchee. node;
@@ -355,15 +356,31 @@ where
355
356
if let ExprLit ( _) = tup_val. node;
356
357
357
358
// next, check the corresponding match arm body to ensure
358
- // this is "{}", or DISPLAY_FMT_METHOD
359
+ // this is DISPLAY_FMT_METHOD
359
360
if let ExprCall ( _, ref body_args) = arm_body_exprs[ idx] . node;
360
361
if body_args. len( ) == 2 ;
361
362
if let ExprPath ( ref body_qpath) = body_args[ 1 ] . node;
362
363
if let Some ( fun_def_id) = opt_def_id( resolve_node( cx, body_qpath, body_args[ 1 ] . hir_id) ) ;
363
- if match_def_path( cx. tcx, fun_def_id, & paths:: DISPLAY_FMT_METHOD ) ||
364
- match_def_path( cx. tcx, fun_def_id, & paths:: DEBUG_FMT_METHOD ) ;
364
+ if match_def_path( cx. tcx, fun_def_id, & paths:: DISPLAY_FMT_METHOD ) ;
365
365
then {
366
- lint_fn( tup_val. span) ;
366
+ if args. len( ) == 2 {
367
+ lint_fn( tup_val. span) ;
368
+ }
369
+
370
+ // ensure the format str has no options (e.g., width, precision, alignment, etc.)
371
+ // and is just "{}"
372
+ if_chain! {
373
+ if args. len( ) == 3 ;
374
+ if let ExprAddrOf ( _, ref format_expr) = args[ 2 ] . node;
375
+ if let ExprArray ( ref format_exprs) = format_expr. node;
376
+ if format_exprs. len( ) >= 1 ;
377
+ if let ExprStruct ( _, ref fields, _) = format_exprs[ idx] . node;
378
+ if let Some ( format_field) = fields. iter( ) . find( |f| f. name. node == "format" ) ;
379
+ if check_unformatted( & format_field. expr) ;
380
+ then {
381
+ lint_fn( tup_val. span) ;
382
+ }
383
+ }
367
384
}
368
385
}
369
386
}
@@ -438,3 +455,33 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
438
455
}
439
456
false
440
457
}
458
+
459
+ /// Checks if the expression matches
460
+ /// ```rust,ignore
461
+ /// &[_ {
462
+ /// format: _ {
463
+ /// width: _::Implied,
464
+ /// ...
465
+ /// },
466
+ /// ...,
467
+ /// }]
468
+ /// ```
469
+ pub fn check_unformatted ( format_field : & Expr ) -> bool {
470
+ if_chain ! {
471
+ if let ExprStruct ( _, ref fields, _) = format_field. node;
472
+ if let Some ( width_field) = fields. iter( ) . find( |f| f. name. node == "width" ) ;
473
+ if let ExprPath ( ref qpath) = width_field. expr. node;
474
+ if last_path_segment( qpath) . name == "Implied" ;
475
+ if let Some ( align_field) = fields. iter( ) . find( |f| f. name. node == "align" ) ;
476
+ if let ExprPath ( ref qpath) = align_field. expr. node;
477
+ if last_path_segment( qpath) . name == "Unknown" ;
478
+ if let Some ( precision_field) = fields. iter( ) . find( |f| f. name. node == "precision" ) ;
479
+ if let ExprPath ( ref qpath_precision) = precision_field. expr. node;
480
+ if last_path_segment( qpath_precision) . name == "Implied" ;
481
+ then {
482
+ return true ;
483
+ }
484
+ }
485
+
486
+ false
487
+ }
0 commit comments