Casts between floats and ints fail to roundtrip properly on `i586-unknown-linux-gnu`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
Doc tests introduced in https://github.com/rust-lang/rust/pull/152512 for f32 and f64 failed in a rollup https://github.com/rust-lang/rust/pull/152616#issuecomment-3902253969 on the i586-unknown-linux-gnu job.
These tests as cast between i32<->f32 and i64<->f64, with no floating point arithmetic performed.
I tried this code:
{ // Max exact integer test, f32
let max_exact_int: i32 = (1 << f32::MANTISSA_DIGITS) - 1;
assert_eq!(max_exact_int, max_exact_int as f32 as i32);
assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f32 as i32);
assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f32 as i32);
// Beyond `f32::MAX_EXACT_INTEGER`, multiple integers can map to one float value
assert_eq!((max_exact_int + 1) as f32, (max_exact_int + 2) as f32);
}
{ // Min exact integer test, f32
let min_exact_int: i32 = -((1 << f32::MANTISSA_DIGITS) - 1);
assert_eq!(min_exact_int, min_exact_int as f32 as i32);
assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f32 as i32);
assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f32 as i32);
// Below `f32::MIN_EXACT_INTEGER`, multiple integers can map to one float value
assert_eq!((min_exact_int - 1) as f32, (min_exact_int - 2) as f32);
}
{ // Max exact integer test, f64
let max_exact_int: i64 = (1 << f64::MANTISSA_DIGITS) - 1;
assert_eq!(max_exact_int, max_exact_int as f64 as i64);
assert_eq!(max_exact_int + 1, (max_exact_int + 1) as f64 as i64);
assert_ne!(max_exact_int + 2, (max_exact_int + 2) as f64 as i64);
// Beyond `f64::MAX_EXACT_INTEGER`, multiple integers can map to one float value
assert_eq!((max_exact_int + 1) as f64, (max_exact_int + 2) as f64);
}
{ // Min exact integer test, f64
let min_exact_int: i64 = -((1 << f64::MANTISSA_DIGITS) - 1);
assert_eq!(min_exact_int, min_exact_int as f64 as i64);
assert_eq!(min_exact_int - 1, (min_exact_int - 1) as f64 as i64);
assert_ne!(min_exact_int - 2, (min_exact_int - 2) as f64 as i64);
// Below `f64::MIN_EXACT_INTEGER`, multiple integers can map to one float value
assert_eq!((min_exact_int - 1) as f64, (min_exact_int - 2) as f64);
}
I expected to see this happen: All 4 of these test blocks should pass
Instead, this happened: All 4 blocks failed
Probably related to https://github.com/rust-lang/rust/issues/114479
Meta
I didn't see the toolchain in the log, but whatever tip of nightly was at 2026-02-14T16:31:07.2087585Z
Backtrace
---
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed::<i32, i32>
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:394:5
4: rust_out::main::_doctest_main_library_core_src_num_f32_rs_528_0
5: rust_out::main
6: <fn() as core::ops::function::FnOnce<()>>::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---- library/core/src/num/f32.rs - f32::f32::MAX_EXACT_INTEGER (line 528) stdout end ----
---
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed::<i32, i32>
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:394:5
4: rust_out::main::_doctest_main_library_core_src_num_f32_rs_555_0
5: rust_out::main
6: <fn() as core::ops::function::FnOnce<()>>::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---- library/core/src/num/f32.rs - f32::f32::MIN_EXACT_INTEGER (line 555) stdout end ----
---
1: core::panicking::panic_fmt
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed::<i64, i64>
4: rust_out::main::_doctest_main_library_core_src_num_f64_rs_527_0
5: rust_out::main
6: <fn() as core::ops::function::FnOnce<()>>::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---- library/core/src/num/f64.rs - f64::f64::MAX_EXACT_INTEGER (line 527) stdout end ----
---
1: core::panicking::panic_fmt
at /rustc/b184b22b186f12ce7b538c7857b49650d492a1fc/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed::<i64, i64>
4: rust_out::main::_doctest_main_library_core_src_num_f64_rs_554_0
5: rust_out::main
6: <fn() as core::ops::function::FnOnce<()>>::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---- library/core/src/num/f64.rs - f64::f64::MIN_EXACT_INTEGER (line 554) stdout end ----
@rustbot label A-floating-point O-x86_32
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the four doctests in library/core/src/num/f32.rs and library/core/src/num/f64.rs on the i586-unknown-linux-gnu job, using the failing assertions and backtrace as the starting point. Read the related issue #114479 to understand the cast behavior being investigated. Done means all four integer-to-float-to-integer roundtrip test blocks pass on that target.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100