Skip to content

Commit feaf179

Browse files
committed
Add lint for iter.nth(0)
- Encourage iter.next() rather than iter.nth(0), which is less readable
1 parent 578e712 commit feaf179

File tree

7 files changed

+90
-2
lines changed

7 files changed

+90
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,7 @@ Released 2018-09-13
11411141
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
11421142
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
11431143
[`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth
1144+
[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero
11441145
[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
11451146
[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero
11461147
[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
88

9-
[There are 342 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
9+
[There are 343 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1010

1111
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1212

clippy_lints/src/iter_nth_zero.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::utils::span_lint_and_sugg;
2+
3+
use rustc::declare_lint_pass;
4+
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
5+
use rustc_errors::Applicability;
6+
use rustc_session::declare_tool_lint;
7+
use syntax::ast::{Expr, ExprKind, PathSegment};
8+
9+
declare_clippy_lint! {
10+
/// **What it does:** Checks for the use of `iter.nth(0)`.
11+
///
12+
/// **Why is this bad?** `iter.nth(0)` is unnecessary, and `iter.next()`
13+
/// is more readable.
14+
///
15+
/// **Known problems:** None.
16+
///
17+
/// **Example:**
18+
///
19+
/// ```rust,ignore
20+
/// // Bad
21+
/// let mut s = HashSet::new();
22+
/// s.insert(1);
23+
/// let x = s.iter().nth(0);
24+
///
25+
/// // Good
26+
/// let mut s = HashSet::new();
27+
/// s.insert(1);
28+
/// let x = s.iter().next();
29+
/// ```
30+
pub ITER_NTH_ZERO,
31+
style,
32+
"replace `iter.nth(0)` with `iter.next()`"
33+
}
34+
35+
declare_lint_pass!(IterNthZero => [ITER_NTH_ZERO]);
36+
37+
impl EarlyLintPass for IterNthZero {
38+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
39+
if let ExprKind::MethodCall(PathSegment { ident, .. }, args) = &expr.kind {
40+
if ident.name.as_str() == "nth" {
41+
if let ExprKind::Lit(literal) = &args[1].kind {
42+
if literal.token.symbol.as_str() == "0" {
43+
span_lint_and_sugg(
44+
cx,
45+
ITER_NTH_ZERO,
46+
expr.span,
47+
"calling `iter.nth(0)` is redundant",
48+
"try",
49+
"using `iter.next()` instead".to_string(),
50+
Applicability::MachineApplicable,
51+
);
52+
}
53+
}
54+
}
55+
}
56+
}
57+
}

clippy_lints/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ pub mod inline_fn_without_body;
217217
pub mod int_plus_one;
218218
pub mod integer_division;
219219
pub mod items_after_statements;
220+
pub mod iter_nth_zero;
220221
pub mod large_enum_variant;
221222
pub mod large_stack_arrays;
222223
pub mod len_zero;
@@ -554,6 +555,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
554555
&int_plus_one::INT_PLUS_ONE,
555556
&integer_division::INTEGER_DIVISION,
556557
&items_after_statements::ITEMS_AFTER_STATEMENTS,
558+
&iter_nth_zero::ITER_NTH_ZERO,
557559
&large_enum_variant::LARGE_ENUM_VARIANT,
558560
&large_stack_arrays::LARGE_STACK_ARRAYS,
559561
&len_zero::LEN_WITHOUT_IS_EMPTY,
@@ -980,6 +982,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
980982
store.register_early_pass(|| box as_conversions::AsConversions);
981983
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
982984
store.register_late_pass(|| box let_underscore::LetUnderscore);
985+
store.register_early_pass(|| box iter_nth_zero::IterNthZero);
983986

984987
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
985988
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1146,6 +1149,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
11461149
LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
11471150
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
11481151
LintId::of(&int_plus_one::INT_PLUS_ONE),
1152+
LintId::of(&iter_nth_zero::ITER_NTH_ZERO),
11491153
LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
11501154
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
11511155
LintId::of(&len_zero::LEN_ZERO),
@@ -1352,6 +1356,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
13521356
LintId::of(&functions::MUST_USE_UNIT),
13531357
LintId::of(&infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH),
13541358
LintId::of(&inherent_to_string::INHERENT_TO_STRING),
1359+
LintId::of(&iter_nth_zero::ITER_NTH_ZERO),
13551360
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
13561361
LintId::of(&len_zero::LEN_ZERO),
13571362
LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),

src/lintlist/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub use lint::Lint;
66
pub use lint::LINT_LEVELS;
77

88
// begin lint list, do not remove this comment, it’s used in `update_lints`
9-
pub const ALL_LINTS: [Lint; 342] = [
9+
pub const ALL_LINTS: [Lint; 343] = [
1010
Lint {
1111
name: "absurd_extreme_comparisons",
1212
group: "correctness",
@@ -875,6 +875,13 @@ pub const ALL_LINTS: [Lint; 342] = [
875875
deprecation: None,
876876
module: "methods",
877877
},
878+
Lint {
879+
name: "iter_nth_zero",
880+
group: "style",
881+
desc: "replace `iter.nth(0)` with `iter.next()`",
882+
deprecation: None,
883+
module: "iter_nth_zero",
884+
},
878885
Lint {
879886
name: "iter_skip_next",
880887
group: "style",

tests/ui/iter_nth_zero.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![warn(clippy::iter_nth_zero)]
2+
use std::collections::HashSet;
3+
4+
fn main() {
5+
let mut s = HashSet::new();
6+
s.insert(1);
7+
let x = s.iter().nth(0);
8+
}

tests/ui/iter_nth_zero.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: calling `iter.nth(0)` is redundant
2+
--> $DIR/iter_nth_zero.rs:7:13
3+
|
4+
LL | let x = s.iter().nth(0);
5+
| ^^^^^^^^^^^^^^^ help: try: `using `iter.next()` instead`
6+
|
7+
= note: `-D clippy::iter-nth-zero` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)