Replace Range::step_by checking with Iterator::step_by
This commit is contained in:
parent
27727c4aff
commit
38925a55b7
7 changed files with 70 additions and 31 deletions
|
|
@ -14,6 +14,16 @@ declare_deprecated_lint! {
|
|||
"`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"
|
||||
}
|
||||
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
/// **Deprecation reason:** `Range::step_by(0)` used to be linted since it's
|
||||
/// an infinite iterator, which is better expressed by `iter::repeat`,
|
||||
/// but the method has been removed for `Iterator::step_by` which panics
|
||||
/// if given a zero
|
||||
declare_deprecated_lint! {
|
||||
pub RANGE_STEP_BY_ZERO,
|
||||
"`iterator.step_by(0)` panics nowadays"
|
||||
}
|
||||
|
||||
/// **What it does:** Nothing. This lint has been deprecated.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -194,6 +194,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||
"extend_from_slice",
|
||||
"`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
|
||||
);
|
||||
store.register_removed(
|
||||
"range_step_by_zero",
|
||||
"`iterator.step_by(0)` panics nowadays",
|
||||
);
|
||||
store.register_removed(
|
||||
"unstable_as_slice",
|
||||
"`Vec::as_slice` has been stabilized in 1.7",
|
||||
|
|
@ -490,7 +494,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
|
|||
ptr::CMP_NULL,
|
||||
ptr::MUT_FROM_REF,
|
||||
ptr::PTR_ARG,
|
||||
ranges::RANGE_STEP_BY_ZERO,
|
||||
ranges::ITERATOR_STEP_BY_ZERO,
|
||||
ranges::RANGE_ZIP_WITH_LEN,
|
||||
reference::DEREF_ADDROF,
|
||||
regex::INVALID_REGEX,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use rustc::lint::*;
|
||||
use rustc::hir::*;
|
||||
use syntax::codemap::Spanned;
|
||||
use utils::{is_integer_literal, match_type, paths, snippet, span_lint};
|
||||
use utils::higher;
|
||||
use utils::{is_integer_literal, paths, snippet, span_lint};
|
||||
use utils::{higher, implements_trait, get_trait_def_id};
|
||||
|
||||
/// **What it does:** Checks for iterating over ranges with a `.step_by(0)`,
|
||||
/// **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
|
||||
|
|
@ -17,10 +17,11 @@ use utils::higher;
|
|||
/// for x in (5..5).step_by(0) { .. }
|
||||
/// ```
|
||||
declare_lint! {
|
||||
pub RANGE_STEP_BY_ZERO,
|
||||
pub ITERATOR_STEP_BY_ZERO,
|
||||
Warn,
|
||||
"using `Range::step_by(0)`, which produces an infinite iterator"
|
||||
"using `Iterator::step_by(0)`, which produces an infinite iterator"
|
||||
}
|
||||
|
||||
/// **What it does:** Checks for zipping a collection with the range of `0.._.len()`.
|
||||
///
|
||||
/// **Why is this bad?** The code is better expressed with `.enumerate()`.
|
||||
|
|
@ -42,7 +43,7 @@ pub struct StepByZero;
|
|||
|
||||
impl LintPass for StepByZero {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(RANGE_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN)
|
||||
lint_array!(ITERATOR_STEP_BY_ZERO, RANGE_ZIP_WITH_LEN)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,12 +53,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero {
|
|||
let name = name.as_str();
|
||||
|
||||
// Range with step_by(0).
|
||||
if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) && is_integer_literal(&args[1], 0) {
|
||||
span_lint(cx,
|
||||
RANGE_STEP_BY_ZERO,
|
||||
expr.span,
|
||||
"Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` \
|
||||
instead");
|
||||
if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) {
|
||||
use consts::{Constant, constant};
|
||||
use rustc_const_math::ConstInt::Usize;
|
||||
if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) {
|
||||
if us.as_u64(cx.sess().target.uint_type) == 0 {
|
||||
span_lint(
|
||||
cx,
|
||||
ITERATOR_STEP_BY_ZERO,
|
||||
expr.span,
|
||||
"Iterator::step_by(0) will panic at runtime",
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if name == "zip" && args.len() == 2 {
|
||||
let iter = &args[0].node;
|
||||
let zip_arg = &args[1];
|
||||
|
|
@ -90,9 +98,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero {
|
|||
fn has_step_by(cx: &LateContext, expr: &Expr) -> bool {
|
||||
// No need for walk_ptrs_ty here because step_by moves self, so it
|
||||
// can't be called on a borrowed range.
|
||||
let ty = cx.tables.expr_ty(expr);
|
||||
let ty = cx.tables.expr_ty_adjusted(expr);
|
||||
|
||||
// Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by
|
||||
match_type(cx, ty, &paths::RANGE) || match_type(cx, ty, &paths::RANGE_FROM) ||
|
||||
match_type(cx, ty, &paths::RANGE_INCLUSIVE)
|
||||
get_trait_def_id(cx, &paths::ITERATOR)
|
||||
.map_or(
|
||||
false,
|
||||
|iterator_trait| implements_trait(cx, ty, iterator_trait, &[])
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue