2 use rustc_front::hir::*;
3 use syntax::codemap::Spanned;
4 use utils::{match_type, is_integer_literal};
7 pub RANGE_STEP_BY_ZERO, Warn,
8 "using Range::step_by(0), which produces an infinite iterator"
12 pub struct StepByZero;
14 impl LintPass for StepByZero {
15 fn get_lints(&self) -> LintArray {
16 lint_array!(RANGE_STEP_BY_ZERO)
20 impl LateLintPass for StepByZero {
21 fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
22 if let ExprMethodCall(Spanned { node: ref name, .. }, _,
23 ref args) = expr.node {
24 // Only warn on literal ranges.
25 if name.as_str() == "step_by" && args.len() == 2 &&
26 is_range(cx, &args[0]) && is_integer_literal(&args[1], 0) {
27 cx.span_lint(RANGE_STEP_BY_ZERO, expr.span,
28 "Range::step_by(0) produces an infinite iterator. \
29 Consider using `std::iter::repeat()` instead")
35 fn is_range(cx: &LateContext, expr: &Expr) -> bool {
36 // No need for walk_ptrs_ty here because step_by moves self, so it
37 // can't be called on a borrowed range.
38 let ty = cx.tcx.expr_ty(expr);
39 // Note: RangeTo and RangeFull don't have step_by
40 match_type(cx, ty, &["core", "ops", "Range"]) || match_type(cx, ty, &["core", "ops", "RangeFrom"])