Skip to content

Commit 06d752e

Browse files
committed
Move RepeatOnce into Methods lint pass
1 parent fd53761 commit 06d752e

File tree

7 files changed

+92
-94
lines changed

7 files changed

+92
-94
lines changed

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
197197
LintId::of(methods::OR_FUN_CALL),
198198
LintId::of(methods::OR_THEN_UNWRAP),
199199
LintId::of(methods::RANGE_ZIP_WITH_LEN),
200+
LintId::of(methods::REPEAT_ONCE),
200201
LintId::of(methods::RESULT_MAP_OR_INTO_OPTION),
201202
LintId::of(methods::SEARCH_IS_SOME),
202203
LintId::of(methods::SHOULD_IMPLEMENT_TRAIT),
@@ -287,7 +288,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
287288
LintId::of(redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
288289
LintId::of(reference::DEREF_ADDROF),
289290
LintId::of(regex::INVALID_REGEX),
290-
LintId::of(repeat_once::REPEAT_ONCE),
291291
LintId::of(returns::LET_AND_RETURN),
292292
LintId::of(returns::NEEDLESS_RETURN),
293293
LintId::of(self_named_constructors::SELF_NAMED_CONSTRUCTORS),

clippy_lints/src/lib.register_complexity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
5252
LintId::of(methods::OPTION_FILTER_MAP),
5353
LintId::of(methods::OR_THEN_UNWRAP),
5454
LintId::of(methods::RANGE_ZIP_WITH_LEN),
55+
LintId::of(methods::REPEAT_ONCE),
5556
LintId::of(methods::SEARCH_IS_SOME),
5657
LintId::of(methods::SKIP_WHILE_NEXT),
5758
LintId::of(methods::UNNECESSARY_FILTER_MAP),
@@ -80,7 +81,6 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
8081
LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
8182
LintId::of(redundant_slicing::REDUNDANT_SLICING),
8283
LintId::of(reference::DEREF_ADDROF),
83-
LintId::of(repeat_once::REPEAT_ONCE),
8484
LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
8585
LintId::of(strlen_on_c_strings::STRLEN_ON_C_STRINGS),
8686
LintId::of(swap::MANUAL_SWAP),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ store.register_lints(&[
346346
methods::OR_THEN_UNWRAP,
347347
methods::PATH_BUF_PUSH_OVERWRITE,
348348
methods::RANGE_ZIP_WITH_LEN,
349+
methods::REPEAT_ONCE,
349350
methods::RESULT_MAP_OR_INTO_OPTION,
350351
methods::SEARCH_IS_SOME,
351352
methods::SHOULD_IMPLEMENT_TRAIT,
@@ -489,7 +490,6 @@ store.register_lints(&[
489490
reference::DEREF_ADDROF,
490491
regex::INVALID_REGEX,
491492
regex::TRIVIAL_REGEX,
492-
repeat_once::REPEAT_ONCE,
493493
return_self_not_must_use::RETURN_SELF_NOT_MUST_USE,
494494
returns::LET_AND_RETURN,
495495
returns::NEEDLESS_RETURN,

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,6 @@ mod redundant_static_lifetimes;
343343
mod ref_option_ref;
344344
mod reference;
345345
mod regex;
346-
mod repeat_once;
347346
mod return_self_not_must_use;
348347
mod returns;
349348
mod same_name_method;
@@ -824,7 +823,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
824823
store.register_late_pass(|| Box::new(macro_use::MacroUseImports::default()));
825824
store.register_late_pass(|| Box::new(pattern_type_mismatch::PatternTypeMismatch));
826825
store.register_late_pass(|| Box::new(stable_sort_primitive::StableSortPrimitive));
827-
store.register_late_pass(|| Box::new(repeat_once::RepeatOnce));
828826
store.register_late_pass(|| Box::new(unwrap_in_result::UnwrapInResult));
829827
store.register_late_pass(|| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
830828
store.register_late_pass(|| Box::new(async_yields_async::AsyncYieldsAsync));

clippy_lints/src/methods/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ mod or_fun_call;
6565
mod or_then_unwrap;
6666
mod path_buf_push_overwrite;
6767
mod range_zip_with_len;
68+
mod repeat_once;
6869
mod search_is_some;
6970
mod single_char_add_str;
7071
mod 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+
27632796
pub 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);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use clippy_utils::consts::{constant_context, Constant};
2+
use clippy_utils::diagnostics::span_lint_and_sugg;
3+
use clippy_utils::source::snippet;
4+
use clippy_utils::ty::is_type_diagnostic_item;
5+
use rustc_errors::Applicability;
6+
use rustc_hir::Expr;
7+
use rustc_lint::LateContext;
8+
use rustc_span::sym;
9+
10+
use super::REPEAT_ONCE;
11+
12+
pub(super) fn check<'tcx>(
13+
cx: &LateContext<'tcx>,
14+
expr: &'tcx Expr<'_>,
15+
recv: &'tcx Expr<'_>,
16+
repeat_arg: &'tcx Expr<'_>,
17+
) {
18+
if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
19+
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
20+
if ty.is_str() {
21+
span_lint_and_sugg(
22+
cx,
23+
REPEAT_ONCE,
24+
expr.span,
25+
"calling `repeat(1)` on str",
26+
"consider using `.to_string()` instead",
27+
format!("{}.to_string()", snippet(cx, recv.span, r#""...""#)),
28+
Applicability::MachineApplicable,
29+
);
30+
} else if ty.builtin_index().is_some() {
31+
span_lint_and_sugg(
32+
cx,
33+
REPEAT_ONCE,
34+
expr.span,
35+
"calling `repeat(1)` on slice",
36+
"consider using `.to_vec()` instead",
37+
format!("{}.to_vec()", snippet(cx, recv.span, r#""...""#)),
38+
Applicability::MachineApplicable,
39+
);
40+
} else if is_type_diagnostic_item(cx, ty, sym::String) {
41+
span_lint_and_sugg(
42+
cx,
43+
REPEAT_ONCE,
44+
expr.span,
45+
"calling `repeat(1)` on a string literal",
46+
"consider using `.clone()` instead",
47+
format!("{}.clone()", snippet(cx, recv.span, r#""...""#)),
48+
Applicability::MachineApplicable,
49+
);
50+
}
51+
}
52+
}

clippy_lints/src/repeat_once.rs

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)