Skip to content

Commit 8babb2d

Browse files
authored
Merge pull request #1250 from elliottneilclark/explicit_into_iter
Add a lint to warn about un-necessary .into_iter()
2 parents 9807c47 + 2e2052a commit 8babb2d

6 files changed

Lines changed: 42 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
## 0.0.93 — ?
5+
* New lint: [`explicit_into_iter_loop`]
6+
47
## 0.0.92 — 2016-09-30
58
* Rustup to *rustc 1.14.0-nightly (289f3a4ca 2016-09-29)*
69

@@ -230,6 +233,7 @@ All notable changes to this project will be documented in this file.
230233
[`eval_order_dependence`]: https://github.com/Manishearth/rust-clippy/wiki#eval_order_dependence
231234
[`expl_impl_clone_on_copy`]: https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy
232235
[`explicit_counter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop
236+
[`explicit_into_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_into_iter_loop
233237
[`explicit_iter_loop`]: https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop
234238
[`extend_from_slice`]: https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice
235239
[`filter_map`]: https://github.com/Manishearth/rust-clippy/wiki#filter_map

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ You can check out this great service at [clippy.bashy.io](https://clippy.bashy.i
174174

175175
## Lints
176176

177-
There are 171 lints included in this crate:
177+
There are 172 lints included in this crate:
178178

179179
name | default | triggers on
180180
---------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
@@ -220,6 +220,7 @@ name
220220
[eval_order_dependence](https://github.com/Manishearth/rust-clippy/wiki#eval_order_dependence) | warn | whether a variable read occurs before a write depends on sub-expression evaluation order
221221
[expl_impl_clone_on_copy](https://github.com/Manishearth/rust-clippy/wiki#expl_impl_clone_on_copy) | warn | implementing `Clone` explicitly on `Copy` types
222222
[explicit_counter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_counter_loop) | warn | for-looping with an explicit counter when `_.enumerate()` would do
223+
[explicit_into_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_into_iter_loop) | warn | for-looping over `_.into_iter()` when `_` would do
223224
[explicit_iter_loop](https://github.com/Manishearth/rust-clippy/wiki#explicit_iter_loop) | warn | for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do
224225
[extend_from_slice](https://github.com/Manishearth/rust-clippy/wiki#extend_from_slice) | warn | `.extend_from_slice(_)` is a faster way to extend a Vec by a slice
225226
[filter_map](https://github.com/Manishearth/rust-clippy/wiki#filter_map) | allow | using combinations of `filter`, `map`, `filter_map` and `flat_map` which can usually be written as a single method call

clippy_lints/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
346346
lifetimes::UNUSED_LIFETIMES,
347347
loops::EMPTY_LOOP,
348348
loops::EXPLICIT_COUNTER_LOOP,
349+
loops::EXPLICIT_INTO_ITER_LOOP,
349350
loops::EXPLICIT_ITER_LOOP,
350351
loops::FOR_KV_MAP,
351352
loops::FOR_LOOP_OVER_OPTION,

clippy_lints/src/loops.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ declare_lint! {
5858
"for-looping over `_.iter()` or `_.iter_mut()` when `&_` or `&mut _` would do"
5959
}
6060

61+
/// **What it does:** Checks for loops on `y.into_iter()` where `y` will do, and
62+
/// suggests the latter.
63+
///
64+
/// **Why is this bad?** Readability.
65+
///
66+
/// **Known problems:** None
67+
///
68+
/// **Example:**
69+
/// ```rust
70+
/// // with `y` a `Vec` or slice:
71+
/// for x in y.into_iter() { .. }
72+
/// ```
73+
declare_lint! {
74+
pub EXPLICIT_INTO_ITER_LOOP,
75+
Warn,
76+
"for-looping over `_.into_iter()` when `_` would do"
77+
}
78+
6179
/// **What it does:** Checks for loops on `x.next()`.
6280
///
6381
/// **Why is this bad?** `next()` returns either `Some(value)` if there was a
@@ -275,6 +293,7 @@ impl LintPass for Pass {
275293
fn get_lints(&self) -> LintArray {
276294
lint_array!(NEEDLESS_RANGE_LOOP,
277295
EXPLICIT_ITER_LOOP,
296+
EXPLICIT_INTO_ITER_LOOP,
278297
ITER_NEXT_LOOP,
279298
FOR_LOOP_OVER_RESULT,
280299
FOR_LOOP_OVER_OPTION,
@@ -577,6 +596,16 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
577596
object,
578597
method_name));
579598
}
599+
} else if method_name.as_str() == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) {
600+
let object = snippet(cx, args[0].span, "_");
601+
span_lint(cx,
602+
EXPLICIT_INTO_ITER_LOOP,
603+
expr.span,
604+
&format!("it is more idiomatic to loop over `{}` instead of `{}.{}()`",
605+
object,
606+
object,
607+
method_name));
608+
580609
} else if method_name.as_str() == "next" && match_trait_method(cx, arg, &paths::ITERATOR) {
581610
span_lint(cx,
582611
ITER_NEXT_LOOP,

clippy_lints/src/utils/paths.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub const HASH: [&'static str; 2] = ["hash", "Hash"];
2323
pub const HASHMAP: [&'static str; 5] = ["std", "collections", "hash", "map", "HashMap"];
2424
pub const HASHMAP_ENTRY: [&'static str; 5] = ["std", "collections", "hash", "map", "Entry"];
2525
pub const HASHSET: [&'static str; 5] = ["std", "collections", "hash", "set", "HashSet"];
26+
pub const INTO_ITERATOR: [&'static str; 4] = ["core", "iter", "traits", "IntoIterator"];
2627
pub const IO_PRINT: [&'static str; 3] = ["std", "io", "_print"];
2728
pub const ITERATOR: [&'static str; 4] = ["core", "iter", "iterator", "Iterator"];
2829
pub const LINKED_LIST: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];

tests/compile-fail/for_loop.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl Unrelated {
8787
}
8888
}
8989

90-
#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)]
90+
#[deny(needless_range_loop, explicit_iter_loop, explicit_into_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)]
9191
#[deny(unused_collect)]
9292
#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity, similar_names)]
9393
#[allow(many_single_char_names)]
@@ -294,6 +294,10 @@ fn main() {
294294
for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec`
295295
for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec`
296296

297+
298+
let out_vec = vec![1,2,3];
299+
for _v in out_vec.into_iter() { } //~ERROR it is more idiomatic to loop over `out_vec` instead of `out_vec.into_iter()`
300+
297301
for _v in &vec { } // these are fine
298302
for _v in &mut vec { } // these are fine
299303

0 commit comments

Comments
 (0)