The following tests do not pass for me, but I think they should, as comparisons with NaN should always simply evaluate to false:
#[test]
fn test_zero_zero() {
assert_eq!(0.0/0.0 < 0.0/0.0, false);
assert_eq!(0.0/0.0 > 0.0/0.0, false);
}
#[test]
fn test_nan_nan() {
assert_eq!(std::f64::NAN < std::f64::NAN, false);
assert_eq!(std::f64::NAN > std::f64::NAN, false);
}
fn main() {
println!("Hello, world!");
}
I get this result on both debug and release builds. I'm on an x86_64 running Linux, rustc 1.27.0-nightly (f0fdaba04 2018-05-15).
Playground link for this test.
https://play.rust-lang.org/?gist=4d6f7f54553b065615caac65b3cb6222&version=nightly&mode=debug
Affects both debug and release, Nightly and Stable.
fn main() {
let operator = std::f64::NAN > std::f64::NAN;
let method = std::f64::NAN.gt(&std::f64::NAN);
println!("{} {}", operator, method); // false false
assert_eq!(operator, method); // doesn't fail
assert_eq!(std::f64::NAN > std::f64::NAN, std::f64::NAN.gt(&std::f64::NAN)); // fails
}
~I think this is an issue with assert_eq! rather than the floating-point comparisons, but I haven't dug into it yet.~
This seems to be a regression introduced by 1.26.
Reduced, related to rvalue promotion I guess.
extern { fn abort() -> !; }
fn main() {
let f = &(std::f64::NAN > std::f64::NAN);
if *f {
unsafe { abort(); }
}
}
Edit: Or maybe a bug in Miri (cc @oli-obk)
extern { fn abort() -> !; }
static B: bool = std::f64::NAN > std::f64::NAN;
fn main() {
if B {
unsafe { abort(); }
}
}
Bisection between c83fa5d91c3b16459ab7b87c48ed18bd059a23af...097efa9a998d4f3a4aee3af126e8f8a9eba1ae07 gives #46882 as the regression PR, as expected.
I guess this logic, which I blindly copied, was never correct to begin with:
https://github.com/rust-lang/rust/blob/master/src/librustc_mir/interpret/operator.rs#L188
I think this is how old const eval did it, and we didn't want to regress that. cc @eddyb
https://github.com/rust-lang/rust/commit/40b118cf4767413f7676c97296c222167604485b#diff-580fb7d0b0ede57fb2ce24a5dd33910cL50
Has the comment about existing bad behaviour.
@oli-obk The old logic used unwrap, meaning NaN > NaN would just ICE (?). I think we can safely replace them directly as PrimVal::from_bool(l > r) etc.
Edit: 馃 The unwrap is in https://github.com/rust-lang/rust/commit/40b118cf4767413f7676c97296c222167604485b#diff-e847a6da94440f7bf6783206efe4275bL138
The incorrect behavior mentioned in https://github.com/rust-lang/rust/issues/50811#issuecomment-389644453 was this:
let x: [u8; (std::f64::NAN > std::f64::NAN) as usize] = [1];
If we fix the float comparison behavior, this code will no longer compile. But I think this is clearly a bug fix and breaking code like this is acceptable.
Most helpful comment
Bisection between c83fa5d91c3b16459ab7b87c48ed18bd059a23af...097efa9a998d4f3a4aee3af126e8f8a9eba1ae07 gives #46882 as the regression PR, as expected.