From 0c7f05dd760b7d1ad329d62268236184e2210c3f Mon Sep 17 00:00:00 2001 From: llogiq Date: Wed, 2 Sep 2015 10:30:11 +0200 Subject: [PATCH] check item name for eq, fixes #268 --- src/misc.rs | 12 ++++++++++++ tests/compile-fail/float_cmp.rs | 25 +++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/misc.rs b/src/misc.rs index b9d74c645b7..5f32a93d3dd 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -4,6 +4,7 @@ use syntax::ast::*; use syntax::ast_util::{is_comparison_binop, binop_to_string}; use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; +use rustc::ast_map::Node::*; use rustc::middle::ty; use utils::{match_path, snippet, span_lint, walk_ptrs_ty}; @@ -91,6 +92,17 @@ impl LintPass for FloatCmp { false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) { return; } + let parent_id = cx.tcx.map.get_parent(expr.id); + match cx.tcx.map.find(parent_id) { + Some(NodeItem(&Item{ ref ident, .. })) | + Some(NodeTraitItem(&TraitItem{ id: _, ref ident, .. })) | + Some(NodeImplItem(&ImplItem{ id: _, ref ident, .. })) => { + let name = ident.name.as_str(); + if &*name == "eq" || name.starts_with("eq_") || + name.ends_with("_eq") { return; } + }, + _ => (), + } span_lint(cx, FLOAT_CMP, expr.span, &format!( "{}-comparison of f32 or f64 detected. Consider changing this to \ `abs({} - {}) < epsilon` for some suitable value of epsilon", diff --git a/tests/compile-fail/float_cmp.rs b/tests/compile-fail/float_cmp.rs index 067ec2818bf..da3dba5e4d4 100755 --- a/tests/compile-fail/float_cmp.rs +++ b/tests/compile-fail/float_cmp.rs @@ -1,6 +1,9 @@ #![feature(plugin)] #![plugin(clippy)] +#![deny(float_cmp)] +#![allow(unused)] + use std::ops::Add; const ZERO : f32 = 0.0; @@ -10,8 +13,26 @@ fn twice(x : T) -> T where T : Add, T : Copy { x + x } -#[deny(float_cmp)] -#[allow(unused)] +fn eq_fl(x: f32, y: f32) -> bool { + if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn +} + +fn fl_eq(x: f32, y: f32) -> bool { + if x.is_nan() { y.is_nan() } else { x == y } // no error, inside "eq" fn +} + +struct X { val: f32 } + +impl PartialEq for X { + fn eq(&self, o: &X) -> bool { + if self.val.is_nan() { + o.val.is_nan() + } else { + self.val == o.val // no error, inside "eq" fn + } + } +} + fn main() { ZERO == 0f32; //no error, comparison with zero is ok ZERO == 0.0; //no error, comparison with zero is ok