From 5912ca986c52041d01384393cbf2da10270738ee Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 4 Mar 2021 23:06:05 +0900 Subject: [PATCH] move iter_nth, iter_nth_zero and iterator_step_by_zero to their own module --- clippy_lints/src/methods/iter_nth.rs | 38 ++++++++++ clippy_lints/src/methods/iter_nth_zero.rs | 27 +++++++ .../src/methods/iterator_step_by_zero.rs | 19 +++++ clippy_lints/src/methods/mod.rs | 74 ++----------------- 4 files changed, 91 insertions(+), 67 deletions(-) create mode 100644 clippy_lints/src/methods/iter_nth.rs create mode 100644 clippy_lints/src/methods/iter_nth_zero.rs create mode 100644 clippy_lints/src/methods/iterator_step_by_zero.rs diff --git a/clippy_lints/src/methods/iter_nth.rs b/clippy_lints/src/methods/iter_nth.rs new file mode 100644 index 00000000000..c8adea9536b --- /dev/null +++ b/clippy_lints/src/methods/iter_nth.rs @@ -0,0 +1,38 @@ +use crate::methods::derefs_to_slice; +use crate::methods::iter_nth_zero; +use crate::utils::{is_type_diagnostic_item, span_lint_and_help}; +use rustc_hir as hir; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::ITER_NTH; + +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &hir::Expr<'_>, + nth_and_iter_args: &[&'tcx [hir::Expr<'tcx>]], + is_mut: bool, +) { + let iter_args = nth_and_iter_args[1]; + let mut_str = if is_mut { "_mut" } else { "" }; + let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0])).is_some() { + "slice" + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vec_type) { + "Vec" + } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym!(vecdeque_type)) { + "VecDeque" + } else { + let nth_args = nth_and_iter_args[0]; + iter_nth_zero::check(cx, expr, &nth_args); + return; // caller is not a type that we want to lint + }; + + span_lint_and_help( + cx, + ITER_NTH, + expr.span, + &format!("called `.iter{0}().nth()` on a {1}", mut_str, caller_type), + None, + &format!("calling `.get{}()` is both faster and more readable", mut_str), + ); +} diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs new file mode 100644 index 00000000000..247192d81f3 --- /dev/null +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -0,0 +1,27 @@ +use crate::consts::{constant, Constant}; +use crate::utils::{match_trait_method, paths, snippet_with_applicability, span_lint_and_sugg}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::ITER_NTH_ZERO; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) { + if_chain! { + if match_trait_method(cx, expr, &paths::ITERATOR); + if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &nth_args[1]); + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + ITER_NTH_ZERO, + expr.span, + "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", + "try calling `.next()` instead of `.nth(0)`", + format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)), + applicability, + ); + } + } +} diff --git a/clippy_lints/src/methods/iterator_step_by_zero.rs b/clippy_lints/src/methods/iterator_step_by_zero.rs new file mode 100644 index 00000000000..3e05d7f76b7 --- /dev/null +++ b/clippy_lints/src/methods/iterator_step_by_zero.rs @@ -0,0 +1,19 @@ +use crate::consts::{constant, Constant}; +use crate::utils::{match_trait_method, paths, span_lint}; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::ITERATOR_STEP_BY_ZERO; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { + if match_trait_method(cx, expr, &paths::ITERATOR) { + if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &args[1]) { + span_lint( + cx, + ITERATOR_STEP_BY_ZERO, + expr.span, + "`Iterator::step_by(0)` will panic at runtime", + ); + } + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 46c9524af55..259d370550c 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -11,6 +11,9 @@ mod inspect_for_each; mod iter_cloned_collect; mod iter_count; mod iter_next_slice; +mod iter_nth; +mod iter_nth_zero; +mod iterator_step_by_zero; mod manual_saturating_arithmetic; mod map_collect_result_unit; mod ok_expect; @@ -43,7 +46,6 @@ use rustc_span::source_map::Span; use rustc_span::symbol::{sym, Symbol, SymbolStr}; use rustc_typeck::hir_ty_to_ty; -use crate::consts::{constant, Constant}; use crate::utils::eager_or_lazy::is_lazyness_candidate; use crate::utils::usage::mutated_variables; use crate::utils::{ @@ -1709,11 +1711,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ["count", "into_iter"] => iter_count::check(cx, expr, &arg_lists[1], "into_iter"), ["count", "iter"] => iter_count::check(cx, expr, &arg_lists[1], "iter"), ["count", "iter_mut"] => iter_count::check(cx, expr, &arg_lists[1], "iter_mut"), - ["nth", "iter"] => lint_iter_nth(cx, expr, &arg_lists, false), - ["nth", "iter_mut"] => lint_iter_nth(cx, expr, &arg_lists, true), + ["nth", "iter"] => iter_nth::check(cx, expr, &arg_lists, false), + ["nth", "iter_mut"] => iter_nth::check(cx, expr, &arg_lists, true), ["nth", "bytes"] => bytes_nth::check(cx, expr, &arg_lists[1]), - ["nth", ..] => lint_iter_nth_zero(cx, expr, arg_lists[0]), - ["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]), + ["nth", ..] => iter_nth_zero::check(cx, expr, arg_lists[0]), + ["step_by", ..] => iterator_step_by_zero::check(cx, expr, arg_lists[0]), ["next", "skip"] => lint_iter_skip_next(cx, expr, arg_lists[1]), ["collect", "cloned"] => iter_cloned_collect::check(cx, expr, arg_lists[1]), ["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]), @@ -2586,68 +2588,6 @@ fn lint_unnecessary_fold(cx: &LateContext<'_>, expr: &hir::Expr<'_>, fold_args: } } -fn lint_step_by<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, args: &'tcx [hir::Expr<'_>]) { - if match_trait_method(cx, expr, &paths::ITERATOR) { - if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &args[1]) { - span_lint( - cx, - ITERATOR_STEP_BY_ZERO, - expr.span, - "`Iterator::step_by(0)` will panic at runtime", - ); - } - } -} - -fn lint_iter_nth<'tcx>( - cx: &LateContext<'tcx>, - expr: &hir::Expr<'_>, - nth_and_iter_args: &[&'tcx [hir::Expr<'tcx>]], - is_mut: bool, -) { - let iter_args = nth_and_iter_args[1]; - let mut_str = if is_mut { "_mut" } else { "" }; - let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.typeck_results().expr_ty(&iter_args[0])).is_some() { - "slice" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vec_type) { - "Vec" - } else if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&iter_args[0]), sym::vecdeque_type) { - "VecDeque" - } else { - let nth_args = nth_and_iter_args[0]; - lint_iter_nth_zero(cx, expr, &nth_args); - return; // caller is not a type that we want to lint - }; - - span_lint_and_help( - cx, - ITER_NTH, - expr.span, - &format!("called `.iter{0}().nth()` on a {1}", mut_str, caller_type), - None, - &format!("calling `.get{}()` is both faster and more readable", mut_str), - ); -} - -fn lint_iter_nth_zero<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_args: &'tcx [hir::Expr<'_>]) { - if_chain! { - if match_trait_method(cx, expr, &paths::ITERATOR); - if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), &nth_args[1]); - then { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - ITER_NTH_ZERO, - expr.span, - "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent", - "try calling `.next()` instead of `.nth(0)`", - format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)), - applicability, - ); - } - } -} - fn lint_iter_skip_next(cx: &LateContext<'_>, expr: &hir::Expr<'_>, skip_args: &[hir::Expr<'_>]) { // lint if caller of skip is an Iterator if match_trait_method(cx, expr, &paths::ITERATOR) {