From 7764dc5ef42754c2704217ebec4a82b964835f54 Mon Sep 17 00:00:00 2001 From: Devon Hollowood Date: Thu, 16 Jun 2016 01:36:11 -0700 Subject: [PATCH] Add slice_iter_nth lint --- CHANGELOG.md | 1 + README.md | 3 ++- clippy_lints/src/lib.rs | 1 + clippy_lints/src/methods.rs | 39 ++++++++++++++++++++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81102a900..30702057b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -234,6 +234,7 @@ All notable changes to this project will be documented in this file. [`single_char_pattern`]: https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern [`single_match`]: https://github.com/Manishearth/rust-clippy/wiki#single_match [`single_match_else`]: https://github.com/Manishearth/rust-clippy/wiki#single_match_else +[`slice_iter_nth`]: https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth [`str_to_string`]: https://github.com/Manishearth/rust-clippy/wiki#str_to_string [`string_add`]: https://github.com/Manishearth/rust-clippy/wiki#string_add [`string_add_assign`]: https://github.com/Manishearth/rust-clippy/wiki#string_add_assign diff --git a/README.md b/README.md index ffda505ee..5707b0ee7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Table of contents: ## Lints -There are 152 lints included in this crate: +There are 153 lints included in this crate: name | default | meaning ---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -140,6 +140,7 @@ name [single_char_pattern](https://github.com/Manishearth/rust-clippy/wiki#single_char_pattern) | warn | using a single-character str where a char could be used, e.g. `_.split("x")` [single_match](https://github.com/Manishearth/rust-clippy/wiki#single_match) | warn | a match statement with a single nontrivial arm (i.e, where the other arm is `_ => {}`) is used; recommends `if let` instead [single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard; recommends `if let` instead +[slice_iter_nth](https://github.com/Manishearth/rust-clippy/wiki#slice_iter_nth) | warn | using `.iter().nth()` on a slice [string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String`; suggests using `push_str()` instead [string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String`; suggests using `push_str()` instead [string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal; suggests using a byte string literal instead diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 42a35e700..072326b1a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -357,6 +357,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { methods::SEARCH_IS_SOME, methods::SHOULD_IMPLEMENT_TRAIT, methods::SINGLE_CHAR_PATTERN, + methods::SLICE_ITER_NTH, methods::TEMPORARY_CSTRING_AS_PTR, methods::WRONG_SELF_CONVENTION, minmax::MIN_MAX, diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9dcc8f9d0..b7d98b5fd 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -312,6 +312,28 @@ declare_lint! { "getting the inner pointer of a temporary `CString`" } +/// **What it does:** This lint checks for use of `.iter().nth()` on a slice. +/// +/// **Why is this bad?** `.get()` is more efficient and more readable. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// ```rust +/// let some_slice = &[0, 1, 2, 3][..]; +/// let third_elem = some_slice.iter().nth(3); +/// ``` +/// The correct use would be: +/// ```rust +/// let some_slice = &[0, 1, 2, 3][..]; +/// let third_elem = some_slice.get(3); +/// ``` +declare_lint! { + pub SLICE_ITER_NTH, + Warn, + "using `.iter().nth()` on a slice" +} + impl LintPass for MethodsPass { fn get_lints(&self) -> LintArray { lint_array!(EXTEND_FROM_SLICE, @@ -330,7 +352,8 @@ impl LintPass for MethodsPass { NEW_RET_NO_SELF, SINGLE_CHAR_PATTERN, SEARCH_IS_SOME, - TEMPORARY_CSTRING_AS_PTR) + TEMPORARY_CSTRING_AS_PTR, + SLICE_ITER_NTH) } } @@ -363,6 +386,8 @@ impl LateLintPass for MethodsPass { lint_extend(cx, expr, arglists[0]); } else if let Some(arglists) = method_chain_args(expr, &["unwrap", "as_ptr"]) { lint_cstring_as_ptr(cx, expr, &arglists[0][0], &arglists[1][0]); + } else if let Some(arglists) = method_chain_args(expr, &["iter", "nth"]) { + lint_slice_iter_nth(cx, expr, arglists[0]); } lint_or_fun_call(cx, expr, &name.node.as_str(), args); @@ -616,6 +641,18 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr }} } +#[allow(ptr_arg)] +// Type of MethodArgs is potentially a Vec +fn lint_slice_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs){ + // lint if the caller of `.iter().nth` is a `slice` + if let Some(_) = derefs_to_slice(cx, &iter_args[0], &cx.tcx.expr_ty(&iter_args[0])) { + span_lint(cx, + SLICE_ITER_NTH, + expr.span, + "called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable"); + } +} + fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: &ty::Ty) -> Option<(Span, &'static str)> { fn may_slice(cx: &LateContext, ty: &ty::Ty) -> bool { match ty.sty {