@@ -47,7 +47,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
47
47
return ;
48
48
}
49
49
match expr. node {
50
-
51
50
// `format!("{}", foo)` expansion
52
51
ExprKind :: Call ( ref fun, ref args) => {
53
52
if_chain ! {
@@ -58,12 +57,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
58
57
if check_single_piece( & args[ 0 ] ) ;
59
58
if let Some ( format_arg) = get_single_string_arg( cx, & args[ 1 ] ) ;
60
59
if check_unformatted( & args[ 2 ] ) ;
60
+ if let ExprKind :: AddrOf ( _, ref format_arg) = format_arg. node;
61
61
then {
62
- let sugg = format!( "{}.to_string()" , snippet( cx, format_arg, "<arg>" ) . into_owned( ) ) ;
62
+ let ( message, sugg) = if_chain! {
63
+ if let ExprKind :: MethodCall ( ref path, ref span, ref expr) = format_arg. node;
64
+ if path. ident. as_interned_str( ) == "to_string" ;
65
+ then {
66
+ ( "`to_string()` is enough" ,
67
+ snippet( cx, format_arg. span, "<arg>" ) . to_string( ) )
68
+ } else {
69
+ ( "consider using .to_string()" ,
70
+ format!( "{}.to_string()" , snippet( cx, format_arg. span, "<arg>" ) ) )
71
+ }
72
+ } ;
73
+
63
74
span_lint_and_then( cx, USELESS_FORMAT , span, "useless use of `format!`" , |db| {
64
75
db. span_suggestion_with_applicability(
65
76
expr. span,
66
- "consider using .to_string()" ,
77
+ message ,
67
78
sugg,
68
79
Applicability :: MachineApplicable ,
69
80
) ;
@@ -114,9 +125,9 @@ fn check_single_piece(expr: &Expr) -> bool {
114
125
/// ::std::fmt::Display::fmt)],
115
126
/// }
116
127
/// ```
117
- /// and that type of `__arg0` is `&str` or `String`
118
- /// then returns the span of first element of the matched tuple
119
- fn get_single_string_arg ( cx : & LateContext < ' _ , ' _ > , expr : & Expr ) -> Option < Span > {
128
+ /// and that the type of `__arg0` is `&str` or `String`,
129
+ /// then returns the span of first element of the matched tuple.
130
+ fn get_single_string_arg < ' a > ( cx : & LateContext < ' _ , ' _ > , expr : & ' a Expr ) -> Option < & ' a Expr > {
120
131
if_chain ! {
121
132
if let ExprKind :: AddrOf ( _, ref expr) = expr. node;
122
133
if let ExprKind :: Match ( ref match_expr, ref arms, _) = expr. node;
@@ -135,7 +146,7 @@ fn get_single_string_arg(cx: &LateContext<'_, '_>, expr: &Expr) -> Option<Span>
135
146
let ty = walk_ptrs_ty( cx. tables. pat_ty( & pat[ 0 ] ) ) ;
136
147
if ty. sty == ty:: Str || match_type( cx, ty, & paths:: STRING ) {
137
148
if let ExprKind :: Tup ( ref values) = match_expr. node {
138
- return Some ( values[ 0 ] . span ) ;
149
+ return Some ( & values[ 0 ] ) ;
139
150
}
140
151
}
141
152
}
@@ -162,9 +173,12 @@ fn check_unformatted(expr: &Expr) -> bool {
162
173
if let ExprKind :: Struct ( _, ref fields, _) = exprs[ 0 ] . node;
163
174
if let Some ( format_field) = fields. iter( ) . find( |f| f. ident. name == "format" ) ;
164
175
if let ExprKind :: Struct ( _, ref fields, _) = format_field. expr. node;
165
- if let Some ( align_field) = fields. iter( ) . find( |f| f. ident. name == "width" ) ;
166
- if let ExprKind :: Path ( ref qpath) = align_field. expr. node;
167
- if last_path_segment( qpath) . ident. name == "Implied" ;
176
+ if let Some ( width_field) = fields. iter( ) . find( |f| f. ident. name == "width" ) ;
177
+ if let ExprKind :: Path ( ref width_qpath) = width_field. expr. node;
178
+ if last_path_segment( width_qpath) . ident. name == "Implied" ;
179
+ if let Some ( precision_field) = fields. iter( ) . find( |f| f. ident. name == "precision" ) ;
180
+ if let ExprKind :: Path ( ref precision_path) = precision_field. expr. node;
181
+ if last_path_segment( precision_path) . ident. name == "Implied" ;
168
182
then {
169
183
return true ;
170
184
}
0 commit comments