-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TryFrom implementation for bool, f32 and f64 #43220
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2504,6 +2504,53 @@ impl fmt::Display for TryFromIntError { | |
} | ||
} | ||
|
||
/// This error will actually never be returned. | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
#[derive(Debug, Copy, Clone)] | ||
pub struct TryFromBoolError {} | ||
|
||
impl TryFromBoolError { | ||
#[unstable(feature = "bool_error_internals", | ||
reason = "available through Error trait and this method should \ | ||
not be exposed publicly", | ||
issue = "0")] | ||
#[doc(hidden)] | ||
pub fn __description(&self) -> &str { | ||
"should not be used" | ||
} | ||
} | ||
|
||
#[unstable(feature = "try_from", issue = "33417")] | ||
impl fmt::Display for TryFromBoolError { | ||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
self.__description().fmt(fmt) | ||
} | ||
} | ||
|
||
#[unstable(feature = "try_from", issue = "33417")] | ||
impl TryFrom<bool> for bool { | ||
type Error = TryFromBoolError; | ||
|
||
fn try_from(u: bool) -> Result<bool, TryFromBoolError> { | ||
Ok(u) | ||
} | ||
} | ||
|
||
macro_rules! try_from_for_bool { | ||
($($source:ty),*) => {$( | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
impl TryFrom<$source> for bool { | ||
type Error = TryFromBoolError; | ||
|
||
fn try_from(u: $source) -> Result<bool, TryFromBoolError> { | ||
Ok(u != 0) | ||
} | ||
} | ||
)*} | ||
} | ||
|
||
try_from_for_bool!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128); | ||
|
||
macro_rules! same_sign_try_from_int_impl { | ||
($storage:ty, $target:ty, $($source:ty),*) => {$( | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
|
@@ -2536,6 +2583,19 @@ same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize); | |
same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize); | ||
same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize); | ||
|
||
same_sign_try_from_int_impl!(f64, usize, f32, f64); | ||
same_sign_try_from_int_impl!(f64, isize, f32, f64); | ||
same_sign_try_from_int_impl!(f64, i128, f32, f64); | ||
same_sign_try_from_int_impl!(f64, u128, f32, f64); | ||
same_sign_try_from_int_impl!(f64, i64, f32, f64); | ||
same_sign_try_from_int_impl!(f64, u64, f32, f64); | ||
same_sign_try_from_int_impl!(f64, i32, f32, f64); | ||
same_sign_try_from_int_impl!(f64, u32, f32, f64); | ||
same_sign_try_from_int_impl!(f64, i16, f32, f64); | ||
same_sign_try_from_int_impl!(f64, u16, f32, f64); | ||
same_sign_try_from_int_impl!(f64, i8, f32, f64); | ||
same_sign_try_from_int_impl!(f64, u8, f32, f64); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For what it's worth the bounds for these conversions are wrong. NaN needs to be taken into account. Also float to int conversions round towards 0 so for example |
||
|
||
macro_rules! cross_sign_from_int_impl { | ||
($unsigned:ty, $($signed:ty),*) => {$( | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
|
@@ -2575,6 +2635,59 @@ cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize); | |
cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize); | ||
cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize); | ||
|
||
/// The error type returned when a checked floating type conversion fails. | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
#[derive(Debug, Copy, Clone)] | ||
pub struct TryFromFloatError(()); | ||
|
||
impl TryFromFloatError { | ||
#[unstable(feature = "float_error_internals", | ||
reason = "available through Error trait and this method should \ | ||
not be exposed publicly", | ||
issue = "0")] | ||
#[doc(hidden)] | ||
pub fn __description(&self) -> &str { | ||
"out of range floating type conversion attempted" | ||
} | ||
} | ||
|
||
#[unstable(feature = "try_from", issue = "33417")] | ||
impl fmt::Display for TryFromFloatError { | ||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||
self.__description().fmt(fmt) | ||
} | ||
} | ||
|
||
macro_rules! try_from_float_impl { | ||
($storage:ty, $target:ident, $($source:ty),*) => {$( | ||
#[unstable(feature = "try_from", issue = "33417")] | ||
impl TryFrom<$source> for $target { | ||
type Error = TryFromFloatError; | ||
|
||
fn try_from(u: $source) -> Result<$target, TryFromFloatError> { | ||
use $target; | ||
|
||
if u.is_nan() { | ||
Ok($target::NAN) | ||
} else if u.is_infinite() { | ||
Ok($target::INFINITY) | ||
} else { | ||
let min = $target::MIN as $storage; | ||
let max = $target::MAX as $storage; | ||
if u as $storage < min || u as $storage > max { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These bounds are also wrong for |
||
Err(TryFromFloatError(())) | ||
} else { | ||
Ok(u as $target) | ||
} | ||
} | ||
} | ||
} | ||
)*} | ||
} | ||
|
||
try_from_float_impl!(f64, f32, f32, f64); | ||
try_from_float_impl!(f64, f64, f32, f64); | ||
|
||
#[doc(hidden)] | ||
trait FromStrRadixHelper: PartialOrd + Copy { | ||
fn min_value() -> Self; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May want to add [inline] here. At least for the integer types, the calls to try_from() didn't inline properly without having [inline], so it might be similar for bool/float.