Skip to content

improve the TryFrom implementations #43248

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

Merged
merged 1 commit into from
Jul 25, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 177 additions & 38 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
@@ -2504,76 +2504,209 @@ impl fmt::Display for TryFromIntError {
}
}

macro_rules! same_sign_try_from_int_impl {
($storage:ty, $target:ty, $($source:ty),*) => {$(
// no possible bounds violation
macro_rules! try_from_unbounded {
($source:ty, $($target:ty),*) => {$(
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this can never fail, shouldn't this be an empty type like enum NeverIntError {}?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh-- but I see there are cfg'd impls of this for usize based on the current target's pointer width, so those would have to be kept as TryFromIntError in order to ensure target compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the infallible ones are moving to a blanket impl, per #33417 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep-- I was suggesting enum NeverIntError {} so that this wouldn't be blocked on never_type. Once never_type and the blanket impl land, NeverIntError can be changed to an alias for !.


#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
let min = <$target as FromStrRadixHelper>::min_value() as $storage;
let max = <$target as FromStrRadixHelper>::max_value() as $storage;
if u as $storage < min || u as $storage > max {
Err(TryFromIntError(()))
} else {
Ok(u as $target)
}
}
)*}
}

// only negative bounds
macro_rules! try_from_lower_bounded {
($source:ty, $($target:ty),*) => {$(
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<$source> for $target {
type Error = TryFromIntError;

#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
if u >= 0 {
Ok(u as $target)
} else {
Err(TryFromIntError(()))
}
}
}
)*}
}

same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize);
same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize);
same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize);
same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize);
same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize);
same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize);
same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize);
same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize);
same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize);
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);

macro_rules! cross_sign_from_int_impl {
($unsigned:ty, $($signed:ty),*) => {$(
// unsigned to signed (only positive bound)
macro_rules! try_from_upper_bounded {
($source:ty, $($target:ty),*) => {$(
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<$unsigned> for $signed {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;

fn try_from(u: $unsigned) -> Result<$signed, TryFromIntError> {
let max = <$signed as FromStrRadixHelper>::max_value() as u128;
if u as u128 > max {
#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
if u > (<$target>::max_value() as $source) {
Err(TryFromIntError(()))
} else {
Ok(u as $signed)
Ok(u as $target)
}
}
}
)*}
}

// all other cases
macro_rules! try_from_both_bounded {
($source:ty, $($target:ty),*) => {$(
#[unstable(feature = "try_from", issue = "33417")]
impl TryFrom<$signed> for $unsigned {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;

fn try_from(u: $signed) -> Result<$unsigned, TryFromIntError> {
let max = <$unsigned as FromStrRadixHelper>::max_value() as u128;
if u < 0 || u as u128 > max {
#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
let min = <$target>::min_value() as $source;
let max = <$target>::max_value() as $source;
if u < min || u > max {
Err(TryFromIntError(()))
} else {
Ok(u as $unsigned)
Ok(u as $target)
}
}
}
)*}
}

cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize);
cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize);
cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize);
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);
macro_rules! rev {
($mac:ident, $source:ty, $($target:ty),*) => {$(
$mac!($target, $source);
)*}
}

/// intra-sign conversions
try_from_unbounded!(u8, u8, u16, u32, u64, u128);
try_from_unbounded!(u16, u16, u32, u64, u128);
try_from_unbounded!(u32, u32, u64, u128);
try_from_unbounded!(u64, u64, u128);
try_from_unbounded!(u128, u128);
try_from_upper_bounded!(u16, u8);
try_from_upper_bounded!(u32, u16, u8);
try_from_upper_bounded!(u64, u32, u16, u8);
try_from_upper_bounded!(u128, u64, u32, u16, u8);

try_from_unbounded!(i8, i8, i16, i32, i64, i128);
try_from_unbounded!(i16, i16, i32, i64, i128);
try_from_unbounded!(i32, i32, i64, i128);
try_from_unbounded!(i64, i64, i128);
try_from_unbounded!(i128, i128);
try_from_both_bounded!(i16, i8);
try_from_both_bounded!(i32, i16, i8);
try_from_both_bounded!(i64, i32, i16, i8);
try_from_both_bounded!(i128, i64, i32, i16, i8);

// unsigned-to-signed
try_from_unbounded!(u8, i16, i32, i64, i128);
try_from_unbounded!(u16, i32, i64, i128);
try_from_unbounded!(u32, i64, i128);
try_from_unbounded!(u64, i128);
try_from_upper_bounded!(u8, i8);
try_from_upper_bounded!(u16, i8, i16);
try_from_upper_bounded!(u32, i8, i16, i32);
try_from_upper_bounded!(u64, i8, i16, i32, i64);
try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);

// signed-to-unsigned
try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
try_from_lower_bounded!(i16, u16, u32, u64, u128);
try_from_lower_bounded!(i32, u32, u64, u128);
try_from_lower_bounded!(i64, u64, u128);
try_from_lower_bounded!(i128, u128);
try_from_both_bounded!(i16, u8);
try_from_both_bounded!(i32, u16, u8);
try_from_both_bounded!(i64, u32, u16, u8);
try_from_both_bounded!(i128, u64, u32, u16, u8);

#[unstable(feature = "try_from", issue = "33417")]
pub use self::ptr_try_from_impls::*;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for? You can't (and don't need to) reexport impls.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really? Because the pub makes them visible where the mods are not. I deem them implementation detail, so I chose to keep them private.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Impls are always visible, even if they're in private modules.


#[cfg(target_pointer_width = "16")]
mod ptr_try_from_impls {
use super::TryFromIntError;
use convert::TryFrom;

try_from_upper_bounded!(usize, u8);
try_from_unbounded!(usize, usize, u16, u32, u64, u128);
try_from_upper_bounded!(usize, i8, i16, isize);
try_from_unbounded!(usize, i32, i64, i128);

try_from_both_bounded!(isize, u8);
try_from_lower_bounded!(isize, usize, u16, u32, u64, u128);
try_from_both_bounded!(isize, i8);
try_from_unbounded!(isize, i16, i32, i64, i128);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it's missing isize to isize. It might be clearer to put the following outside these target specific modules:

try_from_unbounded!(usize, usize);
try_from_upper_bounded!(usize, isize);
try_from_lower_bounded!(isize, usize);
try_from_unbounded!(isize, isize);


rev!(try_from_unbounded, usize, u8, u16);
rev!(try_from_upper_bounded, usize, u32, u64, u128);
rev!(try_from_lower_bounded, usize, i8, i16);
rev!(try_from_both_bounded, usize, i32, i64, i128);

rev!(try_from_unbounded, isize, u8);
rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
rev!(try_from_unbounded, isize, i8, i16);
rev!(try_from_both_bounded, isize, i32, i64, i128);
}

#[cfg(target_pointer_width = "32")]
mod ptr_try_from_impls {
use super::TryFromIntError;
use convert::TryFrom;

try_from_upper_bounded!(usize, u8, u16);
try_from_unbounded!(usize, usize, u32, u64, u128);
try_from_upper_bounded!(usize, i8, i16, i32, isize);
try_from_unbounded!(usize, i64, i128);

try_from_both_bounded!(isize, u8, u16);
try_from_lower_bounded!(isize, usize, u32, u64, u128);
try_from_both_bounded!(isize, i8, i16);
try_from_unbounded!(isize, i32, i64, i128);

rev!(try_from_unbounded, usize, u8, u16, u32);
rev!(try_from_upper_bounded, usize, u64, u128);
rev!(try_from_lower_bounded, usize, i8, i16, i32);
rev!(try_from_both_bounded, usize, i64, i128);

rev!(try_from_unbounded, isize, u8, u16);
rev!(try_from_upper_bounded, isize, u32, u64, u128);
rev!(try_from_unbounded, isize, i8, i16, i32);
rev!(try_from_both_bounded, isize, i64, i128);
}

#[cfg(target_pointer_width = "64")]
mod ptr_try_from_impls {
use super::TryFromIntError;
use convert::TryFrom;

try_from_upper_bounded!(usize, u8, u16, u32);
try_from_unbounded!(usize, usize, u64, u128);
try_from_upper_bounded!(usize, i8, i16, i32, i64, isize);
try_from_unbounded!(usize, i128);

try_from_both_bounded!(isize, u8, u16, u32);
try_from_lower_bounded!(isize, usize, u64, u128);
try_from_both_bounded!(isize, i8, i16, i32);
try_from_unbounded!(isize, i64, i128);

rev!(try_from_unbounded, usize, u8, u16, u32, u64);
rev!(try_from_upper_bounded, usize, u128);
rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
rev!(try_from_both_bounded, usize, i128);

rev!(try_from_unbounded, isize, u8, u16, u32);
rev!(try_from_upper_bounded, isize, u64, u128);
rev!(try_from_unbounded, isize, i8, i16, i32, i64);
rev!(try_from_both_bounded, isize, i128);
}

#[doc(hidden)]
trait FromStrRadixHelper: PartialOrd + Copy {
@@ -2587,15 +2720,21 @@ trait FromStrRadixHelper: PartialOrd + Copy {

macro_rules! doit {
($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
#[inline]
fn min_value() -> Self { Self::min_value() }
#[inline]
fn max_value() -> Self { Self::max_value() }
#[inline]
fn from_u32(u: u32) -> Self { u as Self }
#[inline]
fn checked_mul(&self, other: u32) -> Option<Self> {
Self::checked_mul(*self, other as Self)
}
#[inline]
fn checked_sub(&self, other: u32) -> Option<Self> {
Self::checked_sub(*self, other as Self)
}
#[inline]
fn checked_add(&self, other: u32) -> Option<Self> {
Self::checked_add(*self, other as Self)
}
214 changes: 214 additions & 0 deletions src/libcore/tests/num/mod.rs
Original file line number Diff line number Diff line change
@@ -36,6 +36,26 @@ mod flt2dec;
mod dec2flt;
mod bignum;


/// Adds the attribute to all items in the block.
macro_rules! cfg_block {
($(#[$attr:meta]{$($it:item)*})*) => {$($(
#[$attr]
$it
)*)*}
}

/// Groups items that assume the pointer width is either 16/32/64, and has to be altered if
/// support for larger/smaller pointer widths are added in the future.
macro_rules! assume_usize_width {
{$($it:item)*} => {#[cfg(not(any(
target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64")))]
compile_error!("The current tests of try_from on usize/isize assume that \
the pointer width is either 16, 32, or 64");
$($it)*
}
}

/// Helper function for testing numeric operations
pub fn test_num<T>(ten: T, two: T) where
T: PartialEq
@@ -212,6 +232,8 @@ fn test_f32f64() {
assert!(nan.is_nan());
}


/// Conversions where the full width of $source can be represented as $target
macro_rules! test_impl_try_from_always_ok {
($fn_name:ident, $source:ty, $target: ty) => {
#[test]
@@ -233,36 +255,89 @@ test_impl_try_from_always_ok! { test_try_u8u8, u8, u8 }
test_impl_try_from_always_ok! { test_try_u8u16, u8, u16 }
test_impl_try_from_always_ok! { test_try_u8u32, u8, u32 }
test_impl_try_from_always_ok! { test_try_u8u64, u8, u64 }
test_impl_try_from_always_ok! { test_try_u8u128, u8, u128 }
test_impl_try_from_always_ok! { test_try_u8i16, u8, i16 }
test_impl_try_from_always_ok! { test_try_u8i32, u8, i32 }
test_impl_try_from_always_ok! { test_try_u8i64, u8, i64 }
test_impl_try_from_always_ok! { test_try_u8i128, u8, i128 }

test_impl_try_from_always_ok! { test_try_u16u16, u16, u16 }
test_impl_try_from_always_ok! { test_try_u16u32, u16, u32 }
test_impl_try_from_always_ok! { test_try_u16u64, u16, u64 }
test_impl_try_from_always_ok! { test_try_u16u128, u16, u128 }
test_impl_try_from_always_ok! { test_try_u16i32, u16, i32 }
test_impl_try_from_always_ok! { test_try_u16i64, u16, i64 }
test_impl_try_from_always_ok! { test_try_u16i128, u16, i128 }

test_impl_try_from_always_ok! { test_try_u32u32, u32, u32 }
test_impl_try_from_always_ok! { test_try_u32u64, u32, u64 }
test_impl_try_from_always_ok! { test_try_u32u128, u32, u128 }
test_impl_try_from_always_ok! { test_try_u32i64, u32, i64 }
test_impl_try_from_always_ok! { test_try_u32i128, u32, i128 }

test_impl_try_from_always_ok! { test_try_u64u64, u64, u64 }
test_impl_try_from_always_ok! { test_try_u64u128, u64, u128 }
test_impl_try_from_always_ok! { test_try_u64i128, u64, i128 }

test_impl_try_from_always_ok! { test_try_u128, u128, u128 }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with the other tests this should be test_try_u128u128.


test_impl_try_from_always_ok! { test_try_i8i8, i8, i8 }
test_impl_try_from_always_ok! { test_try_i8i16, i8, i16 }
test_impl_try_from_always_ok! { test_try_i8i32, i8, i32 }
test_impl_try_from_always_ok! { test_try_i8i64, i8, i64 }
test_impl_try_from_always_ok! { test_try_i8i128, i8, i128 }

test_impl_try_from_always_ok! { test_try_i16i16, i16, i16 }
test_impl_try_from_always_ok! { test_try_i16i32, i16, i32 }
test_impl_try_from_always_ok! { test_try_i16i64, i16, i64 }
test_impl_try_from_always_ok! { test_try_i16i128, i16, i128 }

test_impl_try_from_always_ok! { test_try_i32i32, i32, i32 }
test_impl_try_from_always_ok! { test_try_i32i64, i32, i64 }
test_impl_try_from_always_ok! { test_try_i32i128, i32, i128 }

test_impl_try_from_always_ok! { test_try_i64i64, i64, i64 }
test_impl_try_from_always_ok! { test_try_i64i128, i64, i128 }

test_impl_try_from_always_ok! { test_try_i128i128, i128, i128 }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing:

test_impl_try_from_always_ok! { test_try_usizeusize, usize, usize }
test_impl_try_from_always_ok! { test_try_isizeisize, isize, isize }

assume_usize_width! {
test_impl_try_from_always_ok! { test_try_u8usize, u8, usize }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing:

test_impl_try_from_always_ok! { test_try_u8isize, u8, isize }

test_impl_try_from_always_ok! { test_try_i8isize, i8, isize }

test_impl_try_from_always_ok! { test_try_u16usize, u16, usize }
test_impl_try_from_always_ok! { test_try_i16isize, i16, isize }

test_impl_try_from_always_ok! { test_try_usizeu64, usize, u64 }
test_impl_try_from_always_ok! { test_try_usizeu128, usize, u128 }
test_impl_try_from_always_ok! { test_try_usizei128, usize, i128 }

test_impl_try_from_always_ok! { test_try_isizei64, isize, i64 }
test_impl_try_from_always_ok! { test_try_isizei128, isize, i128 }

cfg_block!(
#[cfg(target_pointer_width = "16")] {
test_impl_try_from_always_ok! { test_try_u16usize, u16, usize }
test_impl_try_from_always_ok! { test_try_i16isize, i16, isize }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be:

test_impl_try_from_always_ok! { test_try_usizeu16, usize, u16 }
test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 }

also missing:

test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
test_impl_try_from_always_ok! { test_try_usizei32, usize, i32 }
test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }
test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }

}

#[cfg(target_pointer_width = "32")] {
test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }
test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing:

test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }

}

#[cfg(target_pointer_width = "64")] {
test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
test_impl_try_from_always_ok! { test_try_u64usize, u64, usize }
test_impl_try_from_always_ok! { test_try_i64isize, i64, isize }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing:

test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
test_impl_try_from_always_ok! { test_try_u32isize, u32, isize }

}
);
}

/// Conversions where max of $source can be represented as $target,
macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
($fn_name:ident, $source:ty, $target:ty) => {
#[test]
@@ -285,16 +360,51 @@ test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u8, i8, u8 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u16, i8, u16 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u32, i8, u32 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u64, i8, u64 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8u128, i8, u128 }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u16, i16, u16 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u32, i16, u32 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u64, i16, u64 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16u128, i16, u128 }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u32, i32, u32 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u64, i32, u64 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32u128, i32, u128 }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u64, i64, u64 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64u128, i64, u128 }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i128u128, i128, u128 }

assume_usize_width! {
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i8usize, i8, usize }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i16usize, i16, usize }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu64, isize, u64 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu128, isize, u128 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeusize, isize, usize }

cfg_block!(
#[cfg(target_pointer_width = "16")] {
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu16, isize, u16 }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 }
}

#[cfg(target_pointer_width = "32")] {
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 }

test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize }
}

#[cfg(target_pointer_width = "64")] {
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize }
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64usize, i64, usize }
}
);
}

/// Conversions where max of $source can not be represented as $target,
/// but min can.
macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
($fn_name:ident, $source:ty, $target:ty) => {
#[test]
@@ -325,6 +435,39 @@ test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i16, u64, i16 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i32, u64, i32 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64i64, u64, i64 }

test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i8, u128, i8 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i16, u128, i16 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i32, u128, i32 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i64, u128, i64 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i128, u128, i128 }

assume_usize_width! {
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64isize, u64, isize }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128isize, u128, isize }

test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei8, usize, i8 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei16, usize, i16 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizeisize, usize, isize }

cfg_block!(
#[cfg(target_pointer_width = "16")] {
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u64, isize }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one should be:

test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16isize, u16, isize }

}

#[cfg(target_pointer_width = "32")] {
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 }
}

#[cfg(target_pointer_width = "64")] {
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 }
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei64, usize, i64 }
}
);
}

/// Conversions where min/max of $source can not be represented as $target.
macro_rules! test_impl_try_from_same_sign_err {
($fn_name:ident, $source:ty, $target:ty) => {
#[test]
@@ -359,7 +502,13 @@ test_impl_try_from_same_sign_err! { test_try_u64u8, u64, u8 }
test_impl_try_from_same_sign_err! { test_try_u64u16, u64, u16 }
test_impl_try_from_same_sign_err! { test_try_u64u32, u64, u32 }

test_impl_try_from_same_sign_err! { test_try_u128u8, u128, u8 }
test_impl_try_from_same_sign_err! { test_try_u128u16, u128, u16 }
test_impl_try_from_same_sign_err! { test_try_u128u32, u128, u32 }
test_impl_try_from_same_sign_err! { test_try_u128u64, u128, u64 }

test_impl_try_from_same_sign_err! { test_try_i16i8, i16, i8 }
test_impl_try_from_same_sign_err! { test_try_isizei8, isize, i8 }

test_impl_try_from_same_sign_err! { test_try_i32i8, i32, i8 }
test_impl_try_from_same_sign_err! { test_try_i32i16, i32, i16 }
@@ -368,6 +517,45 @@ 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 }

test_impl_try_from_same_sign_err! { test_try_i128i8, i128, i8 }
test_impl_try_from_same_sign_err! { test_try_i128i16, i128, i16 }
test_impl_try_from_same_sign_err! { test_try_i128i32, i128, i32 }
test_impl_try_from_same_sign_err! { test_try_i128i64, i128, i64 }

assume_usize_width! {
test_impl_try_from_same_sign_err! { test_try_usizeu8, usize, u8 }
test_impl_try_from_same_sign_err! { test_try_u128usize, u128, usize }
test_impl_try_from_same_sign_err! { test_try_i128isize, i128, isize }

cfg_block!(
#[cfg(target_pointer_width = "16")] {
test_impl_try_from_same_sign_err! { test_try_u32usize, u32, usize }
test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize }

test_impl_try_from_same_sign_err! { test_try_i32isize, i32, isize }
test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize }
}

#[cfg(target_pointer_width = "32")] {
test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize }
test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 }

test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize }
test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 }
}

#[cfg(target_pointer_width = "64")] {
test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 }
test_impl_try_from_same_sign_err! { test_try_usizeu32, usize, u32 }

test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 }
test_impl_try_from_same_sign_err! { test_try_isizei32, isize, i32 }
}
);
}

/// Conversinos where neither the min nor the max of $source can be represented by
/// $target, but max/min of the target can be represented by the source.
macro_rules! test_impl_try_from_signed_to_unsigned_err {
($fn_name:ident, $source:ty, $target:ty) => {
#[test]
@@ -400,6 +588,32 @@ 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 }

test_impl_try_from_signed_to_unsigned_err! { test_try_i128u8, i128, u8 }
test_impl_try_from_signed_to_unsigned_err! { test_try_i128u16, i128, u16 }
test_impl_try_from_signed_to_unsigned_err! { test_try_i128u32, i128, u32 }
test_impl_try_from_signed_to_unsigned_err! { test_try_i128u64, i128, u64 }

assume_usize_width! {
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu8, isize, u8 }
test_impl_try_from_signed_to_unsigned_err! { test_try_i128usize, i128, usize }

cfg_block! {
#[cfg(target_pointer_width = "16")] {
test_impl_try_from_signed_to_unsigned_err! { test_try_i32usize, i32, usize }
test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize }
}
#[cfg(target_pointer_width = "32")] {
test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize }

test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 }
}
#[cfg(target_pointer_width = "64")] {
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 }
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu32, isize, u32 }
}
}
}

macro_rules! test_float {
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { mod $modname {
use core::num::Float;