Fix rnd_i clipping floats that don't fit in Fixnum

Fixes #2772.

The current implementation of `rnd_i` incorrectly casts `f` (an `f64`)
into an `i64`, before casting it into an `Integer`.

This fixes that issue by using `Integer::try_from(f)` instead,
and failing if `f` is infinite or NaN.

A fixme is left for a future PR to properly handle the resulting errors
in floor/1 and friends (right now they can only be triggered through FFI).
This commit is contained in:
Emilie Burgun
2025-01-17 20:11:05 +01:00
parent 00e6e323f8
commit 9420c7e41e
2 changed files with 20 additions and 10 deletions

View File

@@ -1044,7 +1044,12 @@ pub(crate) fn sqrt(n1: Number) -> Result<f64, MachineStubGen> {
#[inline]
pub(crate) fn floor(n1: Number, arena: &mut Arena) -> Number {
rnd_i(&n1, arena)
rnd_i(&n1, arena).unwrap_or_else(|_err| {
// FIXME: Currently floor/1 (and several call sites) are infallible,
// but the failing cases (when `n1` is `Number::Float(NAN)` or `Number::Float(INFINITY)`)
// are not reachable with standard is/2 operations.
todo!("Make floor/1 fallible");
})
}
#[inline]