Auto merge of #4275 - jayhardee9:fix/cmp-signum, r=flip1995

Fix float_cmp false positive when comparing signum

fixes #4248

changelog: Fix float_cmp false positive when comparing signum
This commit is contained in:
bors 2019-07-16 07:33:46 +00:00
commit 164310dd8d
2 changed files with 44 additions and 0 deletions

View File

@ -364,6 +364,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
if is_allowed(cx, left) || is_allowed(cx, right) {
return;
}
// Allow comparing the results of signum()
if is_signum(cx, left) && is_signum(cx, right) {
return;
}
if let Some(name) = get_item_name(cx, expr) {
let name = name.as_str();
if name == "eq"
@ -493,6 +499,25 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
}
}
// Return true if `expr` is the result of `signum()` invoked on a float value.
fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
// The negation of a signum is still a signum
if let ExprKind::Unary(UnNeg, ref child_expr) = expr.node {
return is_signum(cx, &child_expr);
}
if_chain! {
if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.node;
if sym!(signum) == method_name.ident.name;
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
// the method call)
then {
return is_float(cx, &expressions[0]);
}
}
false
}
fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::Float(_))
}

View File

@ -77,4 +77,23 @@ fn main() {
let b: *const f32 = xs.as_ptr();
assert_eq!(a, b); // no errors
// no errors - comparing signums is ok
let x32 = 3.21f32;
1.23f32.signum() == x32.signum();
1.23f32.signum() == -(x32.signum());
1.23f32.signum() == 3.21f32.signum();
1.23f32.signum() != x32.signum();
1.23f32.signum() != -(x32.signum());
1.23f32.signum() != 3.21f32.signum();
let x64 = 3.21f64;
1.23f64.signum() == x64.signum();
1.23f64.signum() == -(x64.signum());
1.23f64.signum() == 3.21f64.signum();
1.23f64.signum() != x64.signum();
1.23f64.signum() != -(x64.signum());
1.23f64.signum() != 3.21f64.signum();
}