diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index b4c8521a0a9f..aac9aa3e8ef1 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -92,7 +92,10 @@ impl PartialEq for Constant { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have // `Fw32 == Fw64` so don’t compare them match (ls.parse::(), rs.parse::()) { - (Ok(l), Ok(r)) => l.eq(&r), + // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs + (Ok(l), Ok(r)) => unsafe { + mem::transmute::(l) == mem::transmute::(r) + }, _ => false, } } @@ -159,7 +162,11 @@ impl PartialOrd for Constant { (&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)), (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { match (ls.parse::(), rs.parse::()) { - (Ok(ref l), Ok(ref r)) => l.partial_cmp(r), + (Ok(ref l), Ok(ref r)) => match (l.partial_cmp(r), l.is_sign_positive() == r.is_sign_positive()) { + // Check for comparison of -0.0 and 0.0 + (Some(Ordering::Equal), false) => None, + (x, _) => x + }, _ => None, } } diff --git a/tests/compile-fail/copies.rs b/tests/compile-fail/copies.rs index a8d7157629b4..3c3e43931ed7 100644 --- a/tests/compile-fail/copies.rs +++ b/tests/compile-fail/copies.rs @@ -9,6 +9,7 @@ #![allow(cyclomatic_complexity)] #![allow(blacklisted_name)] #![allow(collapsible_if)] +#![allow(zero_divided_by_zero, eq_op)] fn bar(_: T) {} fn foo() -> bool { unimplemented!() } @@ -229,6 +230,46 @@ fn if_same_then_else() -> Result<&'static str, ()> { _ => 0, }; + let _ = if true { + //~^NOTE same as this + 0.0 + } else { //~ERROR this `if` has identical blocks + 0.0 + }; + + let _ = if true { + //~^NOTE same as this + -0.0 + } else { //~ERROR this `if` has identical blocks + -0.0 + }; + + let _ = if true { + 0.0 + } else { + -0.0 + }; + + // Different NaNs + let _ = if true { + 0.0 / 0.0 + } else { + std::f32::NAN + }; + + // Same NaNs + let _ = if true { + //~^NOTE same as this + std::f32::NAN + } else { //~ERROR this `if` has identical blocks + std::f32::NAN + }; + + let _ = match Some(()) { + Some(()) => 0.0, + None => -0.0 + }; + match (Some(42), Some("")) { (Some(a), None) => bar(a), (None, Some(a)) => bar(a), // bindings have different types diff --git a/tests/consts.rs b/tests/consts.rs index 773b889ebff7..5f5f4cb47d0a 100644 --- a/tests/consts.rs +++ b/tests/consts.rs @@ -82,6 +82,12 @@ fn test_ops() { let half_any = Constant::Float("0.5".into(), FloatWidth::Any); let half32 = Constant::Float("0.5".into(), FloatWidth::F32); let half64 = Constant::Float("0.5".into(), FloatWidth::F64); + let pos_zero = Constant::Float("0.0".into(), FloatWidth::F64); + let neg_zero = Constant::Float("-0.0".into(), FloatWidth::F64); + + assert_eq!(pos_zero, pos_zero); + assert_eq!(neg_zero, neg_zero); + assert_eq!(None, pos_zero.partial_cmp(&neg_zero)); assert_eq!(half_any, half32); assert_eq!(half_any, half64);