Skip to content

Commit

Permalink
Auto merge of rust-lang#4275 - jayhardee9:fix/cmp-signum, r=flip1995
Browse files Browse the repository at this point in the history
Fix float_cmp false positive when comparing signum

fixes rust-lang#4248

changelog: Fix float_cmp false positive when comparing signum
  • Loading branch information
bors committed Jul 16, 2019
2 parents e294815 + 8a8eedf commit 164310d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
25 changes: 25 additions & 0 deletions clippy_lints/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(_))
}
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/float_cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

0 comments on commit 164310d

Please sign in to comment.