Skip to content

Commit 0861fb4

Browse files
committed
Auto merge of #180 - bluss:fix-toprimitive-float, r=cuviper
Fix ToPrimitive for f64 -> f32 conversion. Fix ToPrimitive for f64 -> f32 conversion. It should use the destination type and not the source type to check if the conversion would be to a value that's in range. NOTE: A finite f64 value that is larger than the f32 value range now produces None when converted to f32 with ToPrimitive. Previously, too large f64 values would produce inf f32 values. This `as` cast has an undefined result and was not specified to always produce for example `inf`. The conversion preserves nan/+-inf specifically.
2 parents 1e192c3 + acde249 commit 0861fb4

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

traits/src/cast.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,11 @@ macro_rules! impl_to_primitive_float_to_float {
222222
if size_of::<$SrcT>() <= size_of::<$DstT>() {
223223
Some($slf as $DstT)
224224
} else {
225+
// Make sure the value is in range for the cast.
226+
// NaN and +-inf are cast as they are.
225227
let n = $slf as f64;
226-
let max_value: $SrcT = ::std::$SrcT::MAX;
227-
if -max_value as f64 <= n && n <= max_value as f64 {
228+
let max_value: $DstT = ::std::$DstT::MAX;
229+
if !n.is_finite() || (-max_value as f64 <= n && n <= max_value as f64) {
228230
Some($slf as $DstT)
229231
} else {
230232
None
@@ -431,3 +433,18 @@ impl_num_cast!(i64, to_i64);
431433
impl_num_cast!(isize, to_isize);
432434
impl_num_cast!(f32, to_f32);
433435
impl_num_cast!(f64, to_f64);
436+
437+
438+
#[test]
439+
fn to_primitive_float() {
440+
use std::f32;
441+
use std::f64;
442+
443+
let f32_toolarge = 1e39f64;
444+
assert_eq!(f32_toolarge.to_f32(), None);
445+
assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX));
446+
assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX));
447+
assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY));
448+
assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY));
449+
assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan()));
450+
}

0 commit comments

Comments
 (0)