diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 340028b4beb8e..0b7dc216d416a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -17,6 +17,7 @@ use self::wrapping::OverflowingOps; use char::CharExt; use cmp::{Eq, PartialOrd}; +use convert::From; use fmt; use intrinsics; use marker::{Copy, Sized}; @@ -1471,3 +1472,45 @@ impl fmt::Display for ParseIntError { } pub use num::dec2flt::ParseFloatError; + +// Conversion traits for primitive integer types +// Conversions T -> T are covered by a blanket impl and therefore excluded +// Some conversions from and to usize/isize are not implemented due to portability concerns +macro_rules! impl_from { + ($Small: ty, $Large: ty) => { + #[stable(feature = "lossless_int_conv", since = "1.5.0")] + impl From<$Small> for $Large { + #[stable(feature = "lossless_int_conv", since = "1.5.0")] + #[inline] + fn from(small: $Small) -> $Large { + small as $Large + } + } + } +} + +// Unsigned -> Unsigned +impl_from! { u8, u16 } +impl_from! { u8, u32 } +impl_from! { u8, u64 } +impl_from! { u8, usize } +impl_from! { u16, u32 } +impl_from! { u16, u64 } +impl_from! { u32, u64 } + +// Signed -> Signed +impl_from! { i8, i16 } +impl_from! { i8, i32 } +impl_from! { i8, i64 } +impl_from! { i8, isize } +impl_from! { i16, i32 } +impl_from! { i16, i64 } +impl_from! { i32, i64 } + +// Unsigned -> Signed +impl_from! { u8, i16 } +impl_from! { u8, i32 } +impl_from! { u8, i64 } +impl_from! { u16, i32 } +impl_from! { u16, i64 } +impl_from! { u32, i64 } diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 2a3ff88fe6da2..5e2ec66bababe 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -137,4 +137,44 @@ mod tests { assert_eq!("+".parse::().ok(), None); assert_eq!("".parse::().ok(), None); } + + macro_rules! test_impl_from { + ($fn_name: ident, $Small: ty, $Large: ty) => { + #[test] + fn $fn_name() { + let small_max = <$Small>::max_value(); + let small_min = <$Small>::min_value(); + let large_max: $Large = small_max.into(); + let large_min: $Large = small_min.into(); + assert_eq!(large_max as $Small, small_max); + assert_eq!(large_min as $Small, small_min); + } + } + } + + // Unsigned -> Unsigned + test_impl_from! { test_u8u16, u8, u16 } + test_impl_from! { test_u8u32, u8, u32 } + test_impl_from! { test_u8u64, u8, u64 } + test_impl_from! { test_u8usize, u8, usize } + test_impl_from! { test_u16u32, u16, u32 } + test_impl_from! { test_u16u64, u16, u64 } + test_impl_from! { test_u32u64, u32, u64 } + + // Signed -> Signed + test_impl_from! { test_i8i16, i8, i16 } + test_impl_from! { test_i8i32, i8, i32 } + test_impl_from! { test_i8i64, i8, i64 } + test_impl_from! { test_i8isize, i8, isize } + test_impl_from! { test_i16i32, i16, i32 } + test_impl_from! { test_i16i64, i16, i64 } + test_impl_from! { test_i32i64, i32, i64 } + + // Unsigned -> Signed + test_impl_from! { test_u8i16, u8, i16 } + test_impl_from! { test_u8i32, u8, i32 } + test_impl_from! { test_u8i64, u8, i64 } + test_impl_from! { test_u16i32, u16, i32 } + test_impl_from! { test_u16i64, u16, i64 } + test_impl_from! { test_u32i64, u32, i64 } }