Merge pull request #226 from birkenfeld/fixes

Two small fixes/refactorings
This commit is contained in:
llogiq 2015-08-24 16:21:17 +02:00
commit 961f9d68a9
3 changed files with 19 additions and 13 deletions

View file

@ -1,10 +1,9 @@
use rustc::lint::*; use rustc::lint::*;
use syntax::ast::*; use syntax::ast::*;
use syntax::visit::{Visitor, walk_expr}; use syntax::visit::{Visitor, walk_expr};
use rustc::middle::ty;
use std::collections::HashSet; use std::collections::HashSet;
use utils::{snippet, span_lint, get_parent_expr, match_def_path}; use utils::{snippet, span_lint, get_parent_expr, match_trait_method};
declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn, declare_lint!{ pub NEEDLESS_RANGE_LOOP, Warn,
"for-looping over a range of indices where an iterator over items would do" } "for-looping over a range of indices where an iterator over items would do" }
@ -68,12 +67,7 @@ impl LintPass for LoopsPass {
object, object)); object, object));
// check for looping over Iterator::next() which is not what you want // check for looping over Iterator::next() which is not what you want
} else if method_name == "next" { } else if method_name == "next" {
let method_call = ty::MethodCall::expr(arg.id); if match_trait_method(cx, arg, &["core", "iter", "Iterator"]) {
let trt_id = cx.tcx.tables
.borrow().method_map.get(&method_call)
.and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
if let Some(trt_id) = trt_id {
if match_def_path(cx, trt_id, &["core", "iter", "Iterator"]) {
span_lint(cx, ITER_NEXT_LOOP, expr.span, span_lint(cx, ITER_NEXT_LOOP, expr.span,
"you are iterating over `Iterator::next()` which is an Option; \ "you are iterating over `Iterator::next()` which is an Option; \
this will compile but is probably not what you want"); this will compile but is probably not what you want");
@ -83,7 +77,6 @@ impl LintPass for LoopsPass {
} }
} }
} }
}
} }
/// Recover the essential nodes of a desugared for loop: /// Recover the essential nodes of a desugared for loop:

View file

@ -20,7 +20,7 @@ impl LintPass for StepByZero {
if let ExprMethodCall(Spanned { node: ref ident, .. }, _, if let ExprMethodCall(Spanned { node: ref ident, .. }, _,
ref args) = expr.node { ref args) = expr.node {
// Only warn on literal ranges. // Only warn on literal ranges.
if ident.name.as_str() == "step_by" && args.len() == 2 && if ident.name == "step_by" && args.len() == 2 &&
is_range(cx, &args[0]) && is_lit_zero(&args[1]) { is_range(cx, &args[0]) && is_lit_zero(&args[1]) {
cx.span_lint(RANGE_STEP_BY_ZERO, expr.span, cx.span_lint(RANGE_STEP_BY_ZERO, expr.span,
"Range::step_by(0) produces an infinite iterator. \ "Range::step_by(0) produces an infinite iterator. \

View file

@ -56,6 +56,19 @@ pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
} }
} }
/// check if method call given in "expr" belongs to given trait
pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool {
let method_call = ty::MethodCall::expr(expr.id);
let trt_id = cx.tcx.tables
.borrow().method_map.get(&method_call)
.and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
if let Some(trt_id) = trt_id {
match_def_path(cx, trt_id, path)
} else {
false
}
}
/// match a Path against a slice of segment string literals, e.g. /// match a Path against a slice of segment string literals, e.g.
/// `match_path(path, &["std", "rt", "begin_unwind"])` /// `match_path(path, &["std", "rt", "begin_unwind"])`
pub fn match_path(path: &Path, segments: &[&str]) -> bool { pub fn match_path(path: &Path, segments: &[&str]) -> bool {