diff options
| author | Michael Wright <mikerite@lavabit.com> | 2019-12-18 18:59:43 +0200 |
|---|---|---|
| committer | Michael Wright <mikerite@lavabit.com> | 2019-12-18 18:59:43 +0200 |
| commit | e097fca4df2ff70e0213d747a408d109db16c5d2 (patch) | |
| tree | eb83c0eb013149226fde9b155053d51f77ce9583 /clippy_lints/src/methods | |
| parent | c62396dbf442839fc725d353ef85306da1667caf (diff) | |
| download | rust-e097fca4df2ff70e0213d747a408d109db16c5d2.tar.gz rust-e097fca4df2ff70e0213d747a408d109db16c5d2.zip | |
Update iterator_step_by_zero
Move `iterator_step_by_zero` into `methods` since it applies to all iterators and not just ranges. Simplify the code while doing so.
Diffstat (limited to 'clippy_lints/src/methods')
| -rw-r--r-- | clippy_lints/src/methods/mod.rs | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index ca62e7ea9d2..8e94cc0f002 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -738,6 +738,26 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// **What it does:** Checks for calling `.step_by(0)` on iterators, + /// which never terminates. + /// + /// **Why is this bad?** This very much looks like an oversight, since with + /// `loop { .. }` there is an obvious better way to endlessly loop. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```ignore + /// for x in (5..5).step_by(0) { + /// .. + /// } + /// ``` + pub ITERATOR_STEP_BY_ZERO, + correctness, + "using `Iterator::step_by(0)`, which produces an infinite iterator" +} + +declare_clippy_lint! { /// **What it does:** Checks for use of `.iter().nth()` (and the related /// `.iter_mut().nth()`) on standard library types with O(1) element access. /// @@ -1115,6 +1135,7 @@ declare_lint_pass!(Methods => [ FLAT_MAP_IDENTITY, FIND_MAP, MAP_FLATTEN, + ITERATOR_STEP_BY_ZERO, ITER_NTH, ITER_SKIP_NEXT, GET_UNWRAP, @@ -1173,6 +1194,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { }, ["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false), ["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true), + ["step_by", ..] => lint_step_by(cx, expr, arg_lists[0]), ["next", "skip"] => lint_iter_skip_next(cx, expr), ["collect", "cloned"] => lint_iter_cloned_collect(cx, expr, arg_lists[1]), ["as_ref"] => lint_asref(cx, expr, "as_ref", arg_lists[0]), @@ -1950,6 +1972,20 @@ fn lint_unnecessary_fold(cx: &LateContext<'_, '_>, expr: &hir::Expr, fold_args: } } +fn lint_step_by<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, args: &'tcx [hir::Expr]) { + if match_trait_method(cx, expr, &paths::ITERATOR) { + use crate::consts::{constant, Constant}; + if let Some((Constant::Int(0), _)) = constant(cx, cx.tables, &args[1]) { + span_lint( + cx, + ITERATOR_STEP_BY_ZERO, + expr.span, + "Iterator::step_by(0) will panic at runtime", + ); + } + } +} + fn lint_iter_nth<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, iter_args: &'tcx [hir::Expr], is_mut: bool) { let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { |
