@@ -65,6 +65,7 @@ mod or_fun_call;
6565mod or_then_unwrap;
6666mod path_buf_push_overwrite;
6767mod range_zip_with_len;
68+ mod repeat_once;
6869mod search_is_some;
6970mod single_char_add_str;
7071mod single_char_insert_string;
@@ -2760,6 +2761,38 @@ declare_clippy_lint! {
27602761 "zipping iterator with a range when `enumerate()` would do"
27612762}
27622763
2764+ declare_clippy_lint ! {
2765+ /// ### What it does
2766+ /// Checks for usage of `.repeat(1)` and suggest the following method for each types.
2767+ /// - `.to_string()` for `str`
2768+ /// - `.clone()` for `String`
2769+ /// - `.to_vec()` for `slice`
2770+ ///
2771+ /// The lint will evaluate constant expressions and values as arguments of `.repeat(..)` and emit a message if
2772+ /// they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://github.com/rust-lang/rust-clippy/issues/7306))
2773+ ///
2774+ /// ### Why is this bad?
2775+ /// For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning
2776+ /// the string is the intention behind this, `clone()` should be used.
2777+ ///
2778+ /// ### Example
2779+ /// ```rust
2780+ /// fn main() {
2781+ /// let x = String::from("hello world").repeat(1);
2782+ /// }
2783+ /// ```
2784+ /// Use instead:
2785+ /// ```rust
2786+ /// fn main() {
2787+ /// let x = String::from("hello world").clone();
2788+ /// }
2789+ /// ```
2790+ #[ clippy:: version = "1.47.0" ]
2791+ pub REPEAT_ONCE ,
2792+ complexity,
2793+ "using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` "
2794+ }
2795+
27632796pub struct Methods {
27642797 avoid_breaking_exported_api : bool ,
27652798 msrv : Option < RustcVersion > ,
@@ -2875,6 +2908,7 @@ impl_lint_pass!(Methods => [
28752908 NONSENSICAL_OPEN_OPTIONS ,
28762909 PATH_BUF_PUSH_OVERWRITE ,
28772910 RANGE_ZIP_WITH_LEN ,
2911+ REPEAT_ONCE ,
28782912] ) ;
28792913
28802914/// Extracts a method call name, args, and `Span` of the method name.
@@ -3263,6 +3297,9 @@ impl Methods {
32633297 ( "push" , [ arg] ) => {
32643298 path_buf_push_overwrite:: check ( cx, expr, arg) ;
32653299 } ,
3300+ ( "repeat" , [ arg] ) => {
3301+ repeat_once:: check ( cx, expr, recv, arg) ;
3302+ } ,
32663303 ( "splitn" | "rsplitn" , [ count_arg, pat_arg] ) => {
32673304 if let Some ( ( Constant :: Int ( count) , _) ) = constant ( cx, cx. typeck_results ( ) , count_arg) {
32683305 suspicious_splitn:: check ( cx, name, expr, recv, count) ;
0 commit comments