Skip to content

Casts between floats and ints fail to roundtrip properly on i586-unknown-linux-gnu #152635

@okaneco

Description

@okaneco

Doc tests introduced in #152512 for f32 and f64 failed in a rollup #152616 (comment) 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 #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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-floating-pointArea: Floating point numbers and arithmeticC-bugCategory: This is a bug.O-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions