Skip to content

Commit 33a5b21

Browse files
committed
add a lint for redundant repeat().take()
1 parent 0f9cc8d commit 33a5b21

13 files changed

+147
-16
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5954,6 +5954,7 @@ Released 2018-09-13
59545954
[`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern
59555955
[`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching
59565956
[`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
5957+
[`redundant_repeat_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_repeat_take
59575958
[`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
59585959
[`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
59595960
[`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
456456
crate::methods::READONLY_WRITE_LOCK_INFO,
457457
crate::methods::READ_LINE_WITHOUT_TRIM_INFO,
458458
crate::methods::REDUNDANT_AS_STR_INFO,
459+
crate::methods::REDUNDANT_REPEAT_TAKE_INFO,
459460
crate::methods::REPEAT_ONCE_INFO,
460461
crate::methods::RESULT_FILTER_MAP_INFO,
461462
crate::methods::RESULT_MAP_OR_INTO_OPTION_INFO,

clippy_lints/src/methods/mod.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ mod range_zip_with_len;
9191
mod read_line_without_trim;
9292
mod readonly_write_lock;
9393
mod redundant_as_str;
94+
mod redundant_repeat_take;
9495
mod repeat_once;
9596
mod result_map_or_else_none;
9697
mod search_is_some;
@@ -4284,6 +4285,29 @@ declare_clippy_lint! {
42844285
"map of a trivial closure (not dependent on parameter) over a range"
42854286
}
42864287

4288+
declare_clippy_lint! {
4289+
/// ### What it does
4290+
///
4291+
/// Checks for `repeat().take()` that can be replaced with `repeat_n()`.
4292+
///
4293+
/// ### Why is this bad?
4294+
///
4295+
/// Using `repeat_n()` is more concise and clearer.
4296+
///
4297+
/// ### Example
4298+
/// ```no_run
4299+
/// let _ = std::iter::repeat(10).take(3);
4300+
/// ```
4301+
/// Use instead:
4302+
/// ```no_run
4303+
/// let _ = std::iter::repeat_n(10, 3);
4304+
/// ```
4305+
#[clippy::version = "1.85.0"]
4306+
pub REDUNDANT_REPEAT_TAKE,
4307+
style,
4308+
"detect `repeat().take()` that can be replaced with `repeat_n()`"
4309+
}
4310+
42874311
pub struct Methods {
42884312
avoid_breaking_exported_api: bool,
42894313
msrv: Msrv,
@@ -4449,6 +4473,7 @@ impl_lint_pass!(Methods => [
44494473
MAP_ALL_ANY_IDENTITY,
44504474
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
44514475
UNNECESSARY_MAP_OR,
4476+
REDUNDANT_REPEAT_TAKE,
44524477
]);
44534478

44544479
/// Extracts a method call name, args, and `Span` of the method name.
@@ -5117,6 +5142,7 @@ impl Methods {
51175142
("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
51185143
("take", [arg]) => {
51195144
iter_out_of_bounds::check_take(cx, expr, recv, arg);
5145+
redundant_repeat_take::check(cx, expr, recv, arg);
51205146
if let Some(("cloned", recv2, [], _span2, _)) = method_call(recv) {
51215147
iter_overeager_cloned::check(
51225148
cx,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::source::snippet;
3+
use rustc_errors::Applicability;
4+
use rustc_hir::{Expr, ExprKind, QPath};
5+
use rustc_lint::LateContext;
6+
7+
use super::REDUNDANT_REPEAT_TAKE;
8+
9+
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, repeat_expr: &Expr<'_>, take_arg: &Expr<'_>) {
10+
if !expr.span.from_expansion()
11+
&& let ExprKind::Call(inner, repeat_args) = repeat_expr.kind
12+
&& repeat_args.len() == 1
13+
&& let ExprKind::Path(ref qpath) = inner.kind
14+
&& let QPath::Resolved(_, path) = qpath
15+
&& path.segments.len() == 1
16+
&& path.segments[0].ident.name.as_str() == "repeat"
17+
{
18+
span_lint_and_sugg(
19+
cx,
20+
REDUNDANT_REPEAT_TAKE,
21+
expr.span,
22+
"redundant `repeat().take()`",
23+
"consider using `repeat_n()` instead",
24+
format!(
25+
"std::iter::repeat_n({}, {})",
26+
snippet(cx, repeat_args[0].span, ""),
27+
snippet(cx, take_arg.span, "")
28+
),
29+
Applicability::MachineApplicable,
30+
);
31+
}
32+
}

clippy_utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
clippy::missing_errors_doc,
1616
clippy::missing_panics_doc,
1717
clippy::must_use_candidate,
18+
clippy::redundant_repeat_take,
1819
rustc::diagnostic_outside_of_impl,
1920
rustc::untranslatable_diagnostic
2021
)]

tests/ui/manual_str_repeat.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![allow(non_local_definitions)]
1+
#![allow(non_local_definitions, clippy::redundant_repeat_take)]
22
#![warn(clippy::manual_str_repeat)]
33

44
use std::borrow::Cow;

tests/ui/manual_str_repeat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![allow(non_local_definitions)]
1+
#![allow(non_local_definitions, redundant_repeat_take)]
22
#![warn(clippy::manual_str_repeat)]
33

44
use std::borrow::Cow;

tests/ui/manual_str_repeat.stderr

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
error: lint name `redundant_repeat_take` is deprecated and may not have an effect in the future
2+
--> tests/ui/manual_str_repeat.rs:1:33
3+
|
4+
LL | #![allow(non_local_definitions, redundant_repeat_take)]
5+
| ^^^^^^^^^^^^^^^^^^^^^ help: change it to: `clippy::redundant_repeat_take`
6+
|
7+
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
9+
10+
error: lint name `redundant_repeat_take` is deprecated and may not have an effect in the future
11+
--> tests/ui/manual_str_repeat.rs:1:33
12+
|
13+
LL | #![allow(non_local_definitions, redundant_repeat_take)]
14+
| ^^^^^^^^^^^^^^^^^^^^^ help: change it to: `clippy::redundant_repeat_take`
15+
|
16+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
17+
18+
error: lint name `redundant_repeat_take` is deprecated and may not have an effect in the future
19+
--> tests/ui/manual_str_repeat.rs:1:33
20+
|
21+
LL | #![allow(non_local_definitions, redundant_repeat_take)]
22+
| ^^^^^^^^^^^^^^^^^^^^^ help: change it to: `clippy::redundant_repeat_take`
23+
|
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
126
error: manual implementation of `str::repeat` using iterators
227
--> tests/ui/manual_str_repeat.rs:8:21
328
|
@@ -61,5 +86,5 @@ error: manual implementation of `str::repeat` using iterators
6186
LL | let _: String = std::iter::repeat("test").take(10).collect();
6287
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)`
6388

64-
error: aborting due to 10 previous errors
89+
error: aborting due to 13 previous errors
6590

tests/ui/redundant_repeat_take.fixed

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![warn(clippy::redundant_repeat_take)]
2+
3+
use std::iter::repeat;
4+
5+
fn main() {
6+
let _ = std::iter::repeat_n(10, 3);
7+
8+
let _ = std::iter::repeat_n(String::from("foo"), 4);
9+
10+
for value in std::iter::repeat(5).take(3) {}
11+
12+
let _: Vec<_> = std::iter::repeat(String::from("bar")).take(10).collect();
13+
}

tests/ui/redundant_repeat_take.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![warn(clippy::redundant_repeat_take)]
2+
3+
use std::iter::repeat;
4+
5+
fn main() {
6+
let _ = repeat(10).take(3);
7+
8+
let _ = repeat(String::from("foo")).take(4);
9+
10+
for value in std::iter::repeat(5).take(3) {}
11+
12+
let _: Vec<_> = std::iter::repeat(String::from("bar")).take(10).collect();
13+
}

tests/ui/redundant_repeat_take.stderr

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: redundant `repeat().take()`
2+
--> tests/ui/redundant_repeat_take.rs:6:13
3+
|
4+
LL | let _ = repeat(10).take(3);
5+
| ^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(10, 3)`
6+
|
7+
= note: `-D clippy::redundant-repeat-take` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::redundant_repeat_take)]`
9+
10+
error: redundant `repeat().take()`
11+
--> tests/ui/redundant_repeat_take.rs:8:13
12+
|
13+
LL | let _ = repeat(String::from("foo")).take(4);
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `repeat_n()` instead: `std::iter::repeat_n(String::from("foo"), 4)`
15+
16+
error: aborting due to 2 previous errors
17+

tests/ui/slow_vector_initialization.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(clippy::redundant_repeat_take)]
2+
13
//@no-rustfix
24
use std::iter::repeat;
35
fn main() {

tests/ui/slow_vector_initialization.stderr

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: slow zero-filling initialization
2-
--> tests/ui/slow_vector_initialization.rs:14:5
2+
--> tests/ui/slow_vector_initialization.rs:16:5
33
|
44
LL | let mut vec1 = Vec::with_capacity(len);
55
| ----------------------- help: consider replacing this with: `vec![0; len]`
@@ -10,95 +10,95 @@ LL | vec1.extend(repeat(0).take(len));
1010
= help: to override `-D warnings` add `#[allow(clippy::slow_vector_initialization)]`
1111

1212
error: slow zero-filling initialization
13-
--> tests/ui/slow_vector_initialization.rs:20:5
13+
--> tests/ui/slow_vector_initialization.rs:22:5
1414
|
1515
LL | let mut vec2 = Vec::with_capacity(len - 10);
1616
| ---------------------------- help: consider replacing this with: `vec![0; len - 10]`
1717
LL | vec2.extend(repeat(0).take(len - 10));
1818
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1919

2020
error: slow zero-filling initialization
21-
--> tests/ui/slow_vector_initialization.rs:28:5
21+
--> tests/ui/slow_vector_initialization.rs:30:5
2222
|
2323
LL | let mut vec4 = Vec::with_capacity(len);
2424
| ----------------------- help: consider replacing this with: `vec![0; len]`
2525
LL | vec4.extend(repeat(0).take(vec4.capacity()));
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2727

2828
error: slow zero-filling initialization
29-
--> tests/ui/slow_vector_initialization.rs:39:5
29+
--> tests/ui/slow_vector_initialization.rs:41:5
3030
|
3131
LL | let mut resized_vec = Vec::with_capacity(30);
3232
| ---------------------- help: consider replacing this with: `vec![0; 30]`
3333
LL | resized_vec.resize(30, 0);
3434
| ^^^^^^^^^^^^^^^^^^^^^^^^^
3535

3636
error: slow zero-filling initialization
37-
--> tests/ui/slow_vector_initialization.rs:43:5
37+
--> tests/ui/slow_vector_initialization.rs:45:5
3838
|
3939
LL | let mut extend_vec = Vec::with_capacity(30);
4040
| ---------------------- help: consider replacing this with: `vec![0; 30]`
4141
LL | extend_vec.extend(repeat(0).take(30));
4242
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4343

4444
error: slow zero-filling initialization
45-
--> tests/ui/slow_vector_initialization.rs:51:5
45+
--> tests/ui/slow_vector_initialization.rs:53:5
4646
|
4747
LL | let mut vec1 = Vec::with_capacity(len);
4848
| ----------------------- help: consider replacing this with: `vec![0; len]`
4949
LL | vec1.resize(len, 0);
5050
| ^^^^^^^^^^^^^^^^^^^
5151

5252
error: slow zero-filling initialization
53-
--> tests/ui/slow_vector_initialization.rs:60:5
53+
--> tests/ui/slow_vector_initialization.rs:62:5
5454
|
5555
LL | let mut vec3 = Vec::with_capacity(len - 10);
5656
| ---------------------------- help: consider replacing this with: `vec![0; len - 10]`
5757
LL | vec3.resize(len - 10, 0);
5858
| ^^^^^^^^^^^^^^^^^^^^^^^^
5959

6060
error: slow zero-filling initialization
61-
--> tests/ui/slow_vector_initialization.rs:64:5
61+
--> tests/ui/slow_vector_initialization.rs:66:5
6262
|
6363
LL | let mut vec4 = Vec::with_capacity(len);
6464
| ----------------------- help: consider replacing this with: `vec![0; len]`
6565
LL | vec4.resize(vec4.capacity(), 0);
6666
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6767

6868
error: slow zero-filling initialization
69-
--> tests/ui/slow_vector_initialization.rs:69:5
69+
--> tests/ui/slow_vector_initialization.rs:71:5
7070
|
7171
LL | vec1 = Vec::with_capacity(10);
7272
| ---------------------- help: consider replacing this with: `vec![0; 10]`
7373
LL | vec1.resize(10, 0);
7474
| ^^^^^^^^^^^^^^^^^^
7575

7676
error: slow zero-filling initialization
77-
--> tests/ui/slow_vector_initialization.rs:77:5
77+
--> tests/ui/slow_vector_initialization.rs:79:5
7878
|
7979
LL | let mut vec1 = Vec::new();
8080
| ---------- help: consider replacing this with: `vec![0; len]`
8181
LL | vec1.resize(len, 0);
8282
| ^^^^^^^^^^^^^^^^^^^
8383

8484
error: slow zero-filling initialization
85-
--> tests/ui/slow_vector_initialization.rs:82:5
85+
--> tests/ui/slow_vector_initialization.rs:84:5
8686
|
8787
LL | let mut vec3 = Vec::new();
8888
| ---------- help: consider replacing this with: `vec![0; len - 10]`
8989
LL | vec3.resize(len - 10, 0);
9090
| ^^^^^^^^^^^^^^^^^^^^^^^^
9191

9292
error: slow zero-filling initialization
93-
--> tests/ui/slow_vector_initialization.rs:87:5
93+
--> tests/ui/slow_vector_initialization.rs:89:5
9494
|
9595
LL | vec1 = Vec::new();
9696
| ---------- help: consider replacing this with: `vec![0; 10]`
9797
LL | vec1.resize(10, 0);
9898
| ^^^^^^^^^^^^^^^^^^
9999

100100
error: slow zero-filling initialization
101-
--> tests/ui/slow_vector_initialization.rs:91:5
101+
--> tests/ui/slow_vector_initialization.rs:93:5
102102
|
103103
LL | vec1 = vec![];
104104
| ------ help: consider replacing this with: `vec![0; 10]`

0 commit comments

Comments
 (0)