new lint to check for doomed comparisons to NAN

This commit is contained in:
llogiq 2015-05-04 14:11:15 +02:00
parent 872628e99e
commit 0936e0617a
3 changed files with 55 additions and 1 deletions

View file

@ -28,6 +28,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box misc::MiscPass as LintPassObject); reg.register_lint_pass(box misc::MiscPass as LintPassObject);
reg.register_lint_pass(box misc::StrToStringPass as LintPassObject); reg.register_lint_pass(box misc::StrToStringPass as LintPassObject);
reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject); reg.register_lint_pass(box misc::TopLevelRefPass as LintPassObject);
reg.register_lint_pass(box misc::CmpNan as LintPassObject);
reg.register_lint_pass(box eq_op::EqOp as LintPassObject); reg.register_lint_pass(box eq_op::EqOp as LintPassObject);
reg.register_lint_pass(box bit_mask::BitMask as LintPassObject); reg.register_lint_pass(box bit_mask::BitMask as LintPassObject);
reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject); reg.register_lint_pass(box ptr_arg::PtrArg as LintPassObject);
@ -39,6 +40,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP, misc::TOPLEVEL_REF_ARG, eq_op::EQ_OP,
bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG, bit_mask::BAD_BIT_MASK, ptr_arg::PTR_ARG,
needless_bool::NEEDLESS_BOOL, needless_bool::NEEDLESS_BOOL,
approx_const::APPROX_CONSTANT approx_const::APPROX_CONSTANT,
misc::CMP_NAN
]); ]);
} }

View file

@ -1,6 +1,7 @@
use syntax::ptr::P; use syntax::ptr::P;
use syntax::ast; use syntax::ast;
use syntax::ast::*; use syntax::ast::*;
use syntax::ast_util::is_comparison_binop;
use syntax::visit::{FnKind}; use syntax::visit::{FnKind};
use rustc::lint::{Context, LintPass, LintArray, Lint, Level}; use rustc::lint::{Context, LintPass, LintArray, Lint, Level};
use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr}; use rustc::middle::ty::{self, expr_ty, ty_str, ty_ptr, ty_rptr};
@ -108,3 +109,33 @@ impl LintPass for TopLevelRefPass {
} }
} }
} }
declare_lint!(pub CMP_NAN, Allow, "Deny comparisons to std::f32::NAN or std::f64::NAN");
#[derive(Copy,Clone)]
pub struct CmpNan;
impl LintPass for CmpNan {
fn get_lints(&self) -> LintArray {
lint_array!(CMP_NAN)
}
fn check_expr(&mut self, cx: &Context, expr: &Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
if is_comparison_binop(cmp.node) {
if let &ExprPath(_, ref path) = &left.node {
check_nan(cx, path, expr.span);
}
if let &ExprPath(_, ref path) = &right.node {
check_nan(cx, path, expr.span);
}
}
}
}
}
fn check_nan(cx: &Context, path: &Path, span: Span) {
path.segments.last().map(|seg| if seg.identifier.as_str() == "NAN" {
cx.span_lint(CMP_NAN, span, "Doomed comparison with NAN, use std::{f32,f64}::is_nan instead");
});
}

View file

@ -0,0 +1,21 @@
#![feature(plugin)]
#![plugin(clippy)]
#[deny(cmp_nan)]
fn main() {
let x = 5f32;
x == std::f32::NAN; //~ERROR
x != std::f32::NAN; //~ERROR
x < std::f32::NAN; //~ERROR
x > std::f32::NAN; //~ERROR
x <= std::f32::NAN; //~ERROR
x >= std::f32::NAN; //~ERROR
let y = 0f64;
y == std::f64::NAN; //~ERROR
y != std::f64::NAN; //~ERROR
y < std::f64::NAN; //~ERROR
y > std::f64::NAN; //~ERROR
y <= std::f64::NAN; //~ERROR
y >= std::f64::NAN; //~ERROR
}