Skip to content

Commit 164310d

Browse files
committed
Auto merge of rust-lang#4275 - jayhardee9:fix/cmp-signum, r=flip1995
Fix float_cmp false positive when comparing signum fixes rust-lang#4248 changelog: Fix float_cmp false positive when comparing signum
2 parents e294815 + 8a8eedf commit 164310d

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

clippy_lints/src/misc.rs

+25
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
364364
if is_allowed(cx, left) || is_allowed(cx, right) {
365365
return;
366366
}
367+
368+
// Allow comparing the results of signum()
369+
if is_signum(cx, left) && is_signum(cx, right) {
370+
return;
371+
}
372+
367373
if let Some(name) = get_item_name(cx, expr) {
368374
let name = name.as_str();
369375
if name == "eq"
@@ -493,6 +499,25 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
493499
}
494500
}
495501

502+
// Return true if `expr` is the result of `signum()` invoked on a float value.
503+
fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
504+
// The negation of a signum is still a signum
505+
if let ExprKind::Unary(UnNeg, ref child_expr) = expr.node {
506+
return is_signum(cx, &child_expr);
507+
}
508+
509+
if_chain! {
510+
if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.node;
511+
if sym!(signum) == method_name.ident.name;
512+
// Check that the receiver of the signum() is a float (expressions[0] is the receiver of
513+
// the method call)
514+
then {
515+
return is_float(cx, &expressions[0]);
516+
}
517+
}
518+
false
519+
}
520+
496521
fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
497522
matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::Float(_))
498523
}

tests/ui/float_cmp.rs

+19
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,23 @@ fn main() {
7777
let b: *const f32 = xs.as_ptr();
7878

7979
assert_eq!(a, b); // no errors
80+
81+
// no errors - comparing signums is ok
82+
let x32 = 3.21f32;
83+
1.23f32.signum() == x32.signum();
84+
1.23f32.signum() == -(x32.signum());
85+
1.23f32.signum() == 3.21f32.signum();
86+
87+
1.23f32.signum() != x32.signum();
88+
1.23f32.signum() != -(x32.signum());
89+
1.23f32.signum() != 3.21f32.signum();
90+
91+
let x64 = 3.21f64;
92+
1.23f64.signum() == x64.signum();
93+
1.23f64.signum() == -(x64.signum());
94+
1.23f64.signum() == 3.21f64.signum();
95+
96+
1.23f64.signum() != x64.signum();
97+
1.23f64.signum() != -(x64.signum());
98+
1.23f64.signum() != 3.21f64.signum();
8099
}

0 commit comments

Comments
 (0)