From a2de6e22858a02cfcf6bfc18ff40ebb163ebb07c Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 4 Feb 2017 23:10:28 +0000 Subject: [PATCH] Fix TryFrom for i128/u128 Another case of `as` cast silent truncation being error prone. This also adds a few missing TryFrom tests to libcoretest. --- src/libcore/num/mod.rs | 8 ++++---- src/libcoretest/num/mod.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index e907eae18bcbb..97ea6bb347b54 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2626,8 +2626,8 @@ macro_rules! cross_sign_from_int_impl { type Err = TryFromIntError; fn try_from(u: $unsigned) -> Result<$signed, TryFromIntError> { - let max = <$signed as FromStrRadixHelper>::max_value() as u64; - if u as u64 > max { + let max = <$signed as FromStrRadixHelper>::max_value() as u128; + if u as u128 > max { Err(TryFromIntError(())) } else { Ok(u as $signed) @@ -2640,8 +2640,8 @@ macro_rules! cross_sign_from_int_impl { type Err = TryFromIntError; fn try_from(u: $signed) -> Result<$unsigned, TryFromIntError> { - let max = <$unsigned as FromStrRadixHelper>::max_value() as u64; - if u < 0 || u as u64 > max { + let max = <$unsigned as FromStrRadixHelper>::max_value() as u128; + if u < 0 || u as u128 > max { Err(TryFromIntError(())) } else { Ok(u as $unsigned) diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 4834c0e072c9e..51737c9c3b485 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -366,3 +366,35 @@ test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 } test_impl_try_from_same_sign_err! { test_try_i64i8, i64, i8 } test_impl_try_from_same_sign_err! { test_try_i64i16, i64, i16 } test_impl_try_from_same_sign_err! { test_try_i64i32, i64, i32 } + +macro_rules! test_impl_try_from_signed_to_unsigned_err { + ($fn_name:ident, $source:ty, $target:ty) => { + #[test] + fn $fn_name() { + let max = <$source>::max_value(); + let min = <$source>::min_value(); + let zero: $source = 0; + let t_max = <$target>::max_value(); + let t_min = <$target>::min_value(); + assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); + assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); + assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), + zero as $target); + assert_eq!(<$target as TryFrom<$source>>::try_from(t_max as $source) + .unwrap(), + t_max as $target); + assert_eq!(<$target as TryFrom<$source>>::try_from(t_min as $source) + .unwrap(), + t_min as $target); + } + } +} + +test_impl_try_from_signed_to_unsigned_err! { test_try_i16u8, i16, u8 } + +test_impl_try_from_signed_to_unsigned_err! { test_try_i32u8, i32, u8 } +test_impl_try_from_signed_to_unsigned_err! { test_try_i32u16, i32, u16 } + +test_impl_try_from_signed_to_unsigned_err! { test_try_i64u8, i64, u8 } +test_impl_try_from_signed_to_unsigned_err! { test_try_i64u16, i64, u16 } +test_impl_try_from_signed_to_unsigned_err! { test_try_i64u32, i64, u32 }