Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cast_float_to_int_edge_cases fails on Debian / mips & mipsel #239

Open
sylvestre opened this issue Jun 8, 2022 · 3 comments
Open

cast_float_to_int_edge_cases fails on Debian / mips & mipsel #239

sylvestre opened this issue Jun 8, 2022 · 3 comments

Comments

@sylvestre
Copy link

Full log:
https://buildd.debian.org/status/fetch.php?pkg=rust-num-traits&arch=mipsel&ver=0.2.15-1&stamp=1654173339&raw=0

failures:

---- cast_float_to_int_edge_cases stdout ----
testing cast edge cases for f32 -> isize
  testing min -2147483648
	vs. -2147483648
	and -2147483904
  testing max 2147483520
	vs. 2147483520
	and 2147483648
  testing non-finite values
testing cast edge cases for f32 -> i8
  testing min -128
	vs. -129
	and -129
  testing max 127
	vs. 128
	and 128
  testing non-finite values
testing cast edge cases for f32 -> i16
  testing min -32768
	vs. -32769
	and -32769
  testing max 32767
	vs. 32768
	and 32768
  testing non-finite values
testing cast edge cases for f32 -> i32
  testing min -2147483648
	vs. -2147483648
	and -2147483904
  testing max 2147483520
	vs. 2147483520
	and 2147483648
  testing non-finite values
testing cast edge cases for f32 -> i64
  testing min -9223372036854775808
	vs. -9223372036854775808
	and -9223373136366403584
  testing max 9223371487098961920
	vs. 9223371487098961920
	and 9223372036854775808
  testing non-finite values
testing cast edge cases for f32 -> usize
  testing min 0
	vs. -1
	and -1
  testing max 4294967040
	vs. 4294967040
	and 4294967296
  testing non-finite values
testing cast edge cases for f32 -> u8
  testing min 0
	vs. -1
	and -1
  testing max 255
	vs. 256
	and 256
  testing non-finite values
testing cast edge cases for f32 -> u16
  testing min 0
	vs. -1
	and -1
  testing max 65535
	vs. 65536
	and 65536
  testing non-finite values
testing cast edge cases for f32 -> u32
  testing min 0
	vs. -1
	and -1
  testing max 4294967040
	vs. 4294967040
	and 4294967296
  testing non-finite values
testing cast edge cases for f32 -> u64
  testing min 0
	vs. -1
	and -1
  testing max 18446742974197923840
	vs. 18446742974197923840
	and 18446744073709551616
  testing non-finite values
testing cast edge cases for f64 -> isize
  testing min -2147483648
	vs. -2147483649
	and -2147483649
thread 'cast_float_to_int_edge_cases' panicked at 'assertion failed: `(left == right)`
  left: `Some(-2147483648)`,
 right: `Some(2147483647)`', tests/cast.rs:241:5
stack backtrace:
   0: rust_begin_unwind
             at /usr/src/rustc-1.59.0/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /usr/src/rustc-1.59.0/library/core/src/panicking.rs:116:14
   2: core::panicking::assert_failed_inner
             at /usr/src/rustc-1.59.0/library/core/src/panicking.rs:197:17
   3: core::panicking::assert_failed
             at /usr/src/rustc-1.59.0/library/core/src/panicking.rs:154:5
   4: cast::cast_float_to_int_edge_cases
             at /usr/share/cargo/registry/num-traits-0.2.15/tests/cast.rs:241:5
   5: cast::cast_float_to_int_edge_cases::{{closure}}
             at /usr/share/cargo/registry/num-traits-0.2.15/tests/cast.rs:238:1
   6: core::ops::function::FnOnce::call_once
             at /usr/src/rustc-1.59.0/library/core/src/ops/function.rs:227:5
   7: core::ops::function::FnOnce::call_once
             at /usr/src/rustc-1.59.0/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Can be found on:
https://buildd.debian.org/status/package.php?p=rust-num-traits&suite=sid

Different from:
#151

@cuviper
Copy link
Member

cuviper commented Jun 8, 2022

I don't remember why I put that "{.0}" precision limit in the format string, but unrestricted it looks like this on i686:

testing cast edge cases for f64 -> isize
  testing min -2147483648
        vs. -2147483648.9999995
        and -2147483649

The expectation is that the first "vs." should truncate and cast to Some(isize::MIN), but it looks like your system wrapped around to isize::MAX. The second value is still too large after truncating, so it should cast None, but you didn't get that far.

I'm guessing this is a compiler codegen issue for mips, either in rustc or llvm, but I don't have the means to test mips myself. There's nothing arch-specific about this code though, and it works on other 32-bit targets.

@sylvestre
Copy link
Author

Within Debian, I have access to mips machine. I can do some testing for you if you want :)

@cuviper
Copy link
Member

cuviper commented Jun 8, 2022

I got it working under qemu, although I used static musl, but I don't think libc matters here. It works fine for me on both mips and mipsel, using both rustup stable and 1.59 (like your debian rustc). Can you try on your system with upstream rustc?

Here's an extracted test program you can try as well:

#[cfg(not(target_pointer_width = "32"))]
compile_error!("this test is 32-bit only");

const MIN_M1: f64 = isize::MIN as f64 - 1.0;
const MAX_P1: f64 = isize::MAX as f64 + 1.0;

fn cast(x: f64) -> Option<isize> {
    if x > MIN_M1 && x < MAX_P1 {
        Some(unsafe { x.to_int_unchecked() })
    } else {
        None
    }
}

fn main() {
    dbg!(MIN_M1, MAX_P1);
    for (x, expected) in [
        (-2147483649.0, None),
        (-2147483648.9999995, Some(isize::MIN)),
        (2147483647.9999998, Some(isize::MAX)),
        (2147483648.0, None),
    ] {
        let i = cast(x);
        dbg!(x, i);
        assert_eq!(i, expected);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants