diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index c69026c5c9f3..75c94af30000 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -39,62 +39,51 @@ impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i12 impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -// Conversion traits for primitive integer and float 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 { - (bool => $Int:ty $(,)?) => { - impl_from!( - bool => $Int, - #[stable(feature = "from_bool", since = "1.28.0")], - concat!( - "Converts a [`bool`] to [`", stringify!($Int), "`] losslessly.\n", - "The resulting value is `0` for `false` and `1` for `true` values.\n", - "\n", - "# Examples\n", - "\n", - "```\n", - "assert_eq!(", stringify!($Int), "::from(true), 1);\n", - "assert_eq!(", stringify!($Int), "::from(false), 0);\n", - "```\n", - ), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta] $(,)?) => { - impl_from!( - $Small => $Large, - #[$attr], - concat!("Converts [`", stringify!($Small), "`] to [`", stringify!($Large), "`] losslessly."), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta], $doc:expr $(,)?) => { - #[$attr] +/// Implement `From` for integers +macro_rules! impl_from_bool { + ($($int:ty)*) => {$( + #[stable(feature = "from_bool", since = "1.28.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - impl const From<$Small> for $Large { - // Rustdocs on the impl block show a "[+] show undocumented items" toggle. - // Rustdocs on functions do not. - #[doc = $doc] + impl const From for $int { + /// Converts from [`bool`] to + #[doc = concat!("[`", stringify!($int), "`]")] + /// , by turning `false` into `0` and `true` into `1`. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($int), "::from(false), 0);")] + /// + #[doc = concat!("assert_eq!(", stringify!($int), "::from(true), 1);")] + /// ``` #[inline(always)] - fn from(small: $Small) -> Self { - small as Self + fn from(b: bool) -> Self { + b as Self } } - }; + )*} } // boolean -> integer -impl_from!(bool => u8); -impl_from!(bool => u16); -impl_from!(bool => u32); -impl_from!(bool => u64); -impl_from!(bool => u128); -impl_from!(bool => usize); -impl_from!(bool => i8); -impl_from!(bool => i16); -impl_from!(bool => i32); -impl_from!(bool => i64); -impl_from!(bool => i128); -impl_from!(bool => isize); +impl_from_bool!(u8 u16 u32 u64 u128 usize); +impl_from_bool!(i8 i16 i32 i64 i128 isize); + +/// Implement `From<$small>` for `$large` +macro_rules! impl_from { + ($small:ty => $large:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + impl const From<$small> for $large { + #[doc = concat!("Converts from [`", stringify!($small), "`] to [`", stringify!($large), "`] losslessly.")] + #[inline(always)] + fn from(small: $small) -> Self { + debug_assert!(<$large>::MIN as i128 <= <$small>::MIN as i128); + debug_assert!(<$small>::MAX as u128 <= <$large>::MAX as u128); + small as Self + } + } + } +} // unsigned integer -> unsigned integer impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]);