@@ -2,6 +2,7 @@ use rustc_errors::Applicability;
2
2
use rustc_hir:: { BinOpKind , BorrowKind , Expr , ExprKind , LangItem , QPath } ;
3
3
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
4
4
use rustc_middle:: lint:: in_external_macro;
5
+ use rustc_middle:: ty;
5
6
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
6
7
use rustc_span:: source_map:: Spanned ;
7
8
use rustc_span:: sym;
@@ -11,7 +12,7 @@ use if_chain::if_chain;
11
12
use crate :: utils:: SpanlessEq ;
12
13
use crate :: utils:: {
13
14
get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint,
14
- span_lint_and_sugg,
15
+ span_lint_and_help , span_lint_and_sugg,
15
16
} ;
16
17
17
18
declare_clippy_lint ! {
@@ -289,3 +290,98 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
289
290
}
290
291
}
291
292
}
293
+
294
+ declare_clippy_lint ! {
295
+ /// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`.
296
+ ///
297
+ /// **Why is this bad?** This does a multitude of things to just clone a string. Using `.to_owned()` is more specific.
298
+ ///
299
+ /// **Known problems:** None.
300
+ ///
301
+ /// **Example:**
302
+ ///
303
+ /// ```rust
304
+ /// // example code where clippy issues a warning
305
+ /// let _ = "str".to_string();
306
+ /// ```
307
+ /// Use instead:
308
+ /// ```rust
309
+ /// // example code which does not raise clippy warning
310
+ /// let _ = "str".to_owned();
311
+ /// ```
312
+ pub STR_TO_STRING ,
313
+ restriction,
314
+ "using `to_string()` on a `&str`, which should be `to_owned()`"
315
+ }
316
+
317
+ declare_lint_pass ! ( StrToString => [ STR_TO_STRING ] ) ;
318
+
319
+ impl LateLintPass < ' _ > for StrToString {
320
+ fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & Expr < ' _ > ) {
321
+ if_chain ! {
322
+ if let ExprKind :: MethodCall ( path, _, args, _) = & expr. kind;
323
+ if path. ident. name == sym!( to_string) ;
324
+ let ty = cx. typeck_results( ) . expr_ty( & args[ 0 ] ) ;
325
+ if let ty:: Ref ( _, ty, ..) = ty. kind( ) ;
326
+ if * ty. kind( ) == ty:: Str ;
327
+ then {
328
+ span_lint_and_help(
329
+ cx,
330
+ STR_TO_STRING ,
331
+ expr. span,
332
+ "`to_string()` does a multitude of things to just clone a `&str`" ,
333
+ None ,
334
+ "consider using `.to_owned()`" ,
335
+ ) ;
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ declare_clippy_lint ! {
342
+ /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`.
343
+ ///
344
+ /// **Why is this bad?** This does a multitude of things to just clone a string. Using `.clone()` is more specific.
345
+ ///
346
+ /// **Known problems:** None.
347
+ ///
348
+ /// **Example:**
349
+ ///
350
+ /// ```rust
351
+ /// // example code where clippy issues a warning
352
+ /// let msg = String::from("Hello World");
353
+ /// let _ = msg.to_string();
354
+ /// ```
355
+ /// Use instead:
356
+ /// ```rust
357
+ /// // example code which does not raise clippy warning
358
+ /// let msg = String::from("Hello World");
359
+ /// let _ = msg.clone();
360
+ /// ```
361
+ pub STRING_TO_STRING ,
362
+ restriction,
363
+ "using `to_string()` on a `String`, which should be `clone()`"
364
+ }
365
+
366
+ declare_lint_pass ! ( StringToString => [ STRING_TO_STRING ] ) ;
367
+
368
+ impl LateLintPass < ' _ > for StringToString {
369
+ fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & Expr < ' _ > ) {
370
+ if_chain ! {
371
+ if let ExprKind :: MethodCall ( path, _, args, _) = & expr. kind;
372
+ if path. ident. name == sym!( to_string) ;
373
+ let ty = cx. typeck_results( ) . expr_ty( & args[ 0 ] ) ;
374
+ if is_type_diagnostic_item( cx, ty, sym!( string_type) ) ;
375
+ then {
376
+ span_lint_and_help(
377
+ cx,
378
+ STRING_TO_STRING ,
379
+ expr. span,
380
+ "`to_string()` does a multitude of things to just clone a `String`" ,
381
+ None ,
382
+ "consider using `.clone()`" ,
383
+ ) ;
384
+ }
385
+ }
386
+ }
387
+ }
0 commit comments