Add suggestion for iter_skip_next lint

This commit is contained in:
Dmitry Murzin 2020-07-25 17:09:44 +03:00
parent 79f948ec0a
commit b375f1dd20
No known key found for this signature in database
GPG Key ID: 3DA7EB8E3131A454
4 changed files with 48 additions and 29 deletions

View File

@ -1408,7 +1408,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true), ["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true),
["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]), ["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]),
["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]), ["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]),
["next", "skip"] => lint_iter_skip_next(cx, expr), ["next", "skip"] => lint_iter_skip_next(cx, expr, arg_lists[1]),
["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]),
["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]), ["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]),
["as_mut"] => lint_asref(cx, expr, "as_mut", arg_lists[0]), ["as_mut"] => lint_asref(cx, expr, "as_mut", arg_lists[0]),
@ -2436,17 +2436,21 @@ fn lint_get_unwrap<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, get_args:
); );
} }
fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>) { fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) {
// lint if caller of skip is an Iterator // lint if caller of skip is an Iterator
if match_trait_method(cx, expr, &paths::ITERATOR) { if match_trait_method(cx, expr, &paths::ITERATOR) {
span_lint_and_help( if let [caller, n] = skip_args {
cx, let hint = format!(".nth({})", snippet(cx, n.span, ".."));
ITER_SKIP_NEXT, span_lint_and_sugg(
expr.span, cx,
"called `skip(x).next()` on an iterator", ITER_SKIP_NEXT,
None, expr.span.trim_start(caller.span).unwrap(),
"this is more succinctly expressed by calling `nth(x)`", "called `skip(x).next()` on an iterator",
); "use `nth` instead",
hint,
Applicability::MachineApplicable,
);
}
} }
} }

View File

@ -0,0 +1,22 @@
// run-rustfix
// aux-build:option_helpers.rs
#![warn(clippy::iter_skip_next)]
#![allow(clippy::blacklisted_name)]
#![allow(clippy::iter_nth)]
extern crate option_helpers;
use option_helpers::IteratorFalsePositives;
/// Checks implementation of `ITER_SKIP_NEXT` lint
fn main() {
let some_vec = vec![0, 1, 2, 3];
let _ = some_vec.iter().nth(42);
let _ = some_vec.iter().cycle().nth(42);
let _ = (1..10).nth(10);
let _ = &some_vec[..].iter().nth(3);
let foo = IteratorFalsePositives { foo: 0 };
let _ = foo.skip(42).next();
let _ = foo.filter().skip(42).next();
}

View File

@ -1,15 +1,17 @@
// run-rustfix
// aux-build:option_helpers.rs // aux-build:option_helpers.rs
#![warn(clippy::iter_skip_next)] #![warn(clippy::iter_skip_next)]
#![allow(clippy::blacklisted_name)] #![allow(clippy::blacklisted_name)]
#![allow(clippy::iter_nth)]
extern crate option_helpers; extern crate option_helpers;
use option_helpers::IteratorFalsePositives; use option_helpers::IteratorFalsePositives;
/// Checks implementation of `ITER_SKIP_NEXT` lint /// Checks implementation of `ITER_SKIP_NEXT` lint
fn iter_skip_next() { fn main() {
let mut some_vec = vec![0, 1, 2, 3]; let some_vec = vec![0, 1, 2, 3];
let _ = some_vec.iter().skip(42).next(); let _ = some_vec.iter().skip(42).next();
let _ = some_vec.iter().cycle().skip(42).next(); let _ = some_vec.iter().cycle().skip(42).next();
let _ = (1..10).skip(10).next(); let _ = (1..10).skip(10).next();
@ -18,5 +20,3 @@ fn iter_skip_next() {
let _ = foo.skip(42).next(); let _ = foo.skip(42).next();
let _ = foo.filter().skip(42).next(); let _ = foo.filter().skip(42).next();
} }
fn main() {}

View File

@ -1,35 +1,28 @@
error: called `skip(x).next()` on an iterator error: called `skip(x).next()` on an iterator
--> $DIR/iter_skip_next.rs:13:13 --> $DIR/iter_skip_next.rs:15:28
| |
LL | let _ = some_vec.iter().skip(42).next(); LL | let _ = some_vec.iter().skip(42).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
| |
= note: `-D clippy::iter-skip-next` implied by `-D warnings` = note: `-D clippy::iter-skip-next` implied by `-D warnings`
= help: this is more succinctly expressed by calling `nth(x)`
error: called `skip(x).next()` on an iterator error: called `skip(x).next()` on an iterator
--> $DIR/iter_skip_next.rs:14:13 --> $DIR/iter_skip_next.rs:16:36
| |
LL | let _ = some_vec.iter().cycle().skip(42).next(); LL | let _ = some_vec.iter().cycle().skip(42).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(42)`
|
= help: this is more succinctly expressed by calling `nth(x)`
error: called `skip(x).next()` on an iterator error: called `skip(x).next()` on an iterator
--> $DIR/iter_skip_next.rs:15:13 --> $DIR/iter_skip_next.rs:17:20
| |
LL | let _ = (1..10).skip(10).next(); LL | let _ = (1..10).skip(10).next();
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(10)`
|
= help: this is more succinctly expressed by calling `nth(x)`
error: called `skip(x).next()` on an iterator error: called `skip(x).next()` on an iterator
--> $DIR/iter_skip_next.rs:16:14 --> $DIR/iter_skip_next.rs:18:33
| |
LL | let _ = &some_vec[..].iter().skip(3).next(); LL | let _ = &some_vec[..].iter().skip(3).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(3)`
|
= help: this is more succinctly expressed by calling `nth(x)`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors