From 2178ef8b220daec3228f6f4dae60787e506fa089 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 23 Mar 2018 13:36:08 +0100 Subject: [PATCH 1/5] TryFrom for integers: use From instead for truely-infallible impls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is precendent in C for having a minimum pointer size, but I don’t feel confident enough about the future to mandate a maximum. --- src/libcore/num/mod.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a5ba0bcdf7e66..fa535e0e62836 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3804,14 +3804,11 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8); try_from_unbounded!(isize, i16, i32, i64, i128); - rev!(try_from_unbounded, usize, 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, i16); rev!(try_from_both_bounded, isize, i32, i64, i128); } @@ -3830,14 +3827,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16); try_from_unbounded!(isize, i32, i64, i128); - rev!(try_from_unbounded, usize, u16, u32); + rev!(try_from_unbounded, usize, 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_unbounded, isize, u16); rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i16, i32); + rev!(try_from_unbounded, isize, i32); rev!(try_from_both_bounded, isize, i64, i128); } @@ -3856,14 +3853,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16, i32); try_from_unbounded!(isize, i64, i128); - rev!(try_from_unbounded, usize, u16, u32, u64); + rev!(try_from_unbounded, usize, 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_unbounded, isize, u16, u32); rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i16, i32, i64); + rev!(try_from_unbounded, isize, i32, i64); rev!(try_from_both_bounded, isize, i128); } @@ -4074,6 +4071,20 @@ impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] } impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] } +// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX +// which imply that pointer-sized integers must be at least 16 bits: +// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4 +impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } +impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] } + +// RISC-V defines the possibility of a 128-bit address space (RV128). + +// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf +// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf + + // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. // Lossy float conversions are not implemented at this time. From 9fd399feb149bb7b58f21c54fc8c9358fea487a2 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 23 Mar 2018 13:42:43 +0100 Subject: [PATCH 2/5] =?UTF-8?q?Don=E2=80=99t=20use=20`type=20Error=20=3D?= =?UTF-8?q?=20!`=20for=20target-dependant=20TryFrom=20impls.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead, expose apparently-fallible conversions in cases where the implementation happens to be infallible for a given target. Having an associated type / return type in a public API change based on the target is a portability hazard. --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index fa535e0e62836..2da5718a358d1 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3681,7 +3681,7 @@ macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( #[unstable(feature = "try_from", issue = "33417")] impl TryFrom<$source> for $target { - type Error = !; + type Error = TryFromIntError; #[inline] fn try_from(value: $source) -> Result { From e53a2a72743810e05f58c61c9d8a4c89b712ad2e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 23 Mar 2018 13:52:54 +0100 Subject: [PATCH 3/5] Stabilize the TryFrom and TryInto traits Tracking issue: https://github.com/rust-lang/rust/issues/33417 --- src/libcore/array.rs | 6 +++--- src/libcore/char.rs | 6 +++--- src/libcore/convert.rs | 12 ++++++++---- src/libcore/num/mod.rs | 14 +++++++------- src/libcore/tests/lib.rs | 1 - src/librustc_apfloat/lib.rs | 2 +- src/libstd/error.rs | 6 +++--- src/libstd/lib.rs | 1 - src/libstd_unicode/char.rs | 2 +- src/libstd_unicode/lib.rs | 1 - src/test/ui/e0119/conflict-with-std.rs | 2 -- src/test/ui/e0119/conflict-with-std.stderr | 6 +++--- 12 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 3d24f8902bd83..87144c27c9e11 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -59,7 +59,7 @@ unsafe impl> FixedSizeArray for A { } /// The error type returned when a conversion from a slice to an array fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Debug, Copy, Clone)] pub struct TryFromSliceError(()); @@ -148,7 +148,7 @@ macro_rules! array_impls { } } - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] { type Error = TryFromSliceError; @@ -162,7 +162,7 @@ macro_rules! array_impls { } } - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] { type Error = TryFromSliceError; diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 1638f9710f597..bbeebf52a73c1 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -265,7 +265,7 @@ impl FromStr for char { } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryFrom for char { type Error = CharTryFromError; @@ -280,11 +280,11 @@ impl TryFrom for char { } /// The error type returned when a conversion from u32 to char fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct CharTryFromError(()); -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl fmt::Display for CharTryFromError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "converted integer out of range for `char`".fmt(f) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 7324df95bc5d5..637213957848c 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -322,22 +322,26 @@ pub trait From: Sized { /// /// [`TryFrom`]: trait.TryFrom.html /// [`Into`]: trait.Into.html -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. + #[stable(feature = "try_from", since = "1.26.0")] fn try_into(self) -> Result; } /// Attempt to construct `Self` via a conversion. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. + #[stable(feature = "try_from", since = "1.26.0")] type Error; /// Performs the conversion. + #[stable(feature = "try_from", since = "1.26.0")] fn try_from(value: T) -> Result; } @@ -405,7 +409,7 @@ impl From for T { // TryFrom implies TryInto -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryInto for T where U: TryFrom { type Error = U::Error; @@ -417,7 +421,7 @@ impl TryInto for T where U: TryFrom // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl TryFrom for T where T: From { type Error = !; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 2da5718a358d1..8f7e8d0c8ab78 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3647,7 +3647,7 @@ macro_rules! from_str_radix_int_impl { from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } /// The error type returned when a checked integral type conversion fails. -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] #[derive(Debug, Copy, Clone)] pub struct TryFromIntError(()); @@ -3662,14 +3662,14 @@ impl TryFromIntError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl fmt::Display for TryFromIntError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.__description().fmt(fmt) } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl From for TryFromIntError { fn from(never: !) -> TryFromIntError { never @@ -3679,7 +3679,7 @@ impl From for TryFromIntError { // no possible bounds violation macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3694,7 +3694,7 @@ macro_rules! try_from_unbounded { // only negative bounds macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3713,7 +3713,7 @@ macro_rules! try_from_lower_bounded { // unsigned to signed (only positive bound) macro_rules! try_from_upper_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; @@ -3732,7 +3732,7 @@ macro_rules! try_from_upper_bounded { // all other cases macro_rules! try_from_both_bounded { ($source:ty, $($target:ty),*) => {$( - #[unstable(feature = "try_from", issue = "33417")] + #[stable(feature = "try_from", since = "1.26.0")] impl TryFrom<$source> for $target { type Error = TryFromIntError; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 0b70f69240367..1a68f04532d20 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -43,7 +43,6 @@ #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] -#![feature(try_from)] #![feature(try_trait)] #![feature(exact_chunks)] #![feature(atomic_nand)] diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 2ee7bea84765c..6f08fcf702595 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -48,7 +48,7 @@ #![cfg_attr(stage0, feature(slice_patterns))] #![cfg_attr(stage0, feature(i128_type))] -#![feature(try_from)] +#![cfg_attr(stage0, feature(try_from))] // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 79bb6af168fa0..3d0c96585b552 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -275,14 +275,14 @@ impl Error for num::ParseIntError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for num::TryFromIntError { fn description(&self) -> &str { self.__description() } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for array::TryFromSliceError { fn description(&self) -> &str { self.__description() @@ -356,7 +356,7 @@ impl Error for cell::BorrowMutError { } } -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] impl Error for char::CharTryFromError { fn description(&self) -> &str { "converted integer out of range for `char`" diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 93996868f16c7..15a22443b6af7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -310,7 +310,6 @@ #![feature(test, rustc_private)] #![feature(thread_local)] #![feature(toowned_clone_into)] -#![feature(try_from)] #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unicode)] diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index de8b46d5f1b02..33e47ade8cb9c 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -42,7 +42,7 @@ pub use core::char::{EscapeDebug, EscapeDefault, EscapeUnicode}; pub use core::char::ParseCharError; // unstable re-exports -#[unstable(feature = "try_from", issue = "33417")] +#[stable(feature = "try_from", since = "1.26.0")] pub use core::char::CharTryFromError; #[unstable(feature = "decode_utf8", issue = "33906")] pub use core::char::{DecodeUtf8, decode_utf8}; diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index f155b62e3cc72..c22ea1671fa59 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -39,7 +39,6 @@ #![feature(lang_items)] #![feature(non_exhaustive)] #![feature(staged_api)] -#![feature(try_from)] #![feature(unboxed_closures)] mod bool_trie; diff --git a/src/test/ui/e0119/conflict-with-std.rs b/src/test/ui/e0119/conflict-with-std.rs index ed9033ad53d56..a9f747d09ec2d 100644 --- a/src/test/ui/e0119/conflict-with-std.rs +++ b/src/test/ui/e0119/conflict-with-std.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(try_from)] - use std::marker::PhantomData; use std::convert::{TryFrom, AsRef}; diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index e8b2c84c0df0b..417ff1de3f817 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `std::convert::AsRef` for type `std::boxed::Box`: - --> $DIR/conflict-with-std.rs:17:1 + --> $DIR/conflict-with-std.rs:15:1 | LL | impl AsRef for Box { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | impl AsRef for Box { //~ ERROR conflicting implementations where T: ?Sized; error[E0119]: conflicting implementations of trait `std::convert::From` for type `S`: - --> $DIR/conflict-with-std.rs:24:1 + --> $DIR/conflict-with-std.rs:22:1 | LL | impl From for S { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | impl From for S { //~ ERROR conflicting implementations - impl std::convert::From for T; error[E0119]: conflicting implementations of trait `std::convert::TryFrom` for type `X`: - --> $DIR/conflict-with-std.rs:31:1 + --> $DIR/conflict-with-std.rs:29:1 | LL | impl TryFrom for X { //~ ERROR conflicting implementations | ^^^^^^^^^^^^^^^^^^^^^ From 09008cc23ff6395c2c928f3690e07d7389d08ebc Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 26 Mar 2018 11:17:31 +0200 Subject: [PATCH 4/5] Add TryFrom and TryInto to the prelude --- src/libcore/prelude/v1.rs | 3 +++ src/libstd/prelude/v1.rs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index d43496c387cb8..2c8e27abac9c0 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -39,6 +39,9 @@ pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; +#[stable(feature = "try_from", since = "1.26.0")] +#[doc(no_inline)] +pub use convert::{TryFrom, TryInto}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use default::Default; diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index feedd4e1abe5f..d5b7c68a3fa86 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -35,6 +35,8 @@ #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From}; +#[stable(feature = "try_from", since = "1.26.0")] +#[doc(no_inline)] pub use convert::{TryFrom, TryInto}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use default::Default; #[stable(feature = "rust1", since = "1.0.0")] From 837d6c70233715a0ae8e15c703d40e3046a2f36a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 26 Mar 2018 22:48:12 +0200 Subject: [PATCH 5/5] Remove TryFrom impls that might become conditionally-infallible with a portability lint https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243 --- src/libcore/iter/range.rs | 74 +++++++++++++++++++- src/libcore/num/mod.rs | 70 +++---------------- src/libcore/tests/num/mod.rs | 127 ----------------------------------- src/libstd/io/cursor.rs | 20 +++++- 4 files changed, 100 insertions(+), 191 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 8d1080bb876ef..72b48b565719c 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -91,7 +91,7 @@ macro_rules! step_impl_unsigned { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$t>::try_from(n) { + match <$t>::private_try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), Err(_) => None, } @@ -123,7 +123,7 @@ macro_rules! step_impl_signed { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$unsigned>::try_from(n) { + match <$unsigned>::private_try_from(n) { Ok(n_as_unsigned) => { // Wrapping in unsigned space handles cases like // `-120_i8.add_usize(200) == Some(80_i8)`, @@ -461,3 +461,73 @@ impl DoubleEndedIterator for ops::RangeInclusive { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeInclusive {} + +/// Compensate removal of some impls per +/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243 +trait PrivateTryFromUsize: Sized { + fn private_try_from(n: usize) -> Result; +} + +impl PrivateTryFromUsize for T where T: TryFrom { + #[inline] + fn private_try_from(n: usize) -> Result { + T::try_from(n).map_err(|_| ()) + } +} + +// no possible bounds violation +macro_rules! try_from_unbounded { + ($($target:ty),*) => {$( + impl PrivateTryFromUsize for $target { + #[inline] + fn private_try_from(value: usize) -> Result { + Ok(value as $target) + } + } + )*} +} + +// unsigned to signed (only positive bound) +macro_rules! try_from_upper_bounded { + ($($target:ty),*) => {$( + impl PrivateTryFromUsize for $target { + #[inline] + fn private_try_from(u: usize) -> Result<$target, ()> { + if u > (<$target>::max_value() as usize) { + Err(()) + } else { + Ok(u as $target) + } + } + } + )*} +} + + +#[cfg(target_pointer_width = "16")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_unbounded!(u16, u32, u64, u128); + try_from_unbounded!(i32, i64, i128); +} + +#[cfg(target_pointer_width = "32")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_upper_bounded!(u16); + try_from_unbounded!(u32, u64, u128); + try_from_upper_bounded!(i32); + try_from_unbounded!(i64, i128); +} + +#[cfg(target_pointer_width = "64")] +mod ptr_try_from_impls { + use super::PrivateTryFromUsize; + + try_from_upper_bounded!(u16, u32); + try_from_unbounded!(u64, u128); + try_from_upper_bounded!(i32, i64); + try_from_unbounded!(i128); +} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 8f7e8d0c8ab78..ee041e1e4f1d9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3676,21 +3676,6 @@ impl From for TryFromIntError { } } -// no possible bounds violation -macro_rules! try_from_unbounded { - ($source:ty, $($target:ty),*) => {$( - #[stable(feature = "try_from", since = "1.26.0")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - - #[inline] - fn try_from(value: $source) -> Result { - Ok(value as $target) - } - } - )*} -} - // only negative bounds macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( @@ -3789,27 +3774,20 @@ try_from_both_bounded!(i128, u64, u32, u16, u8); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); +try_from_upper_bounded!(usize, u8); +try_from_upper_bounded!(usize, i8, i16); +try_from_both_bounded!(isize, u8); +try_from_both_bounded!(isize, i8); + #[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, u16, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16); - try_from_unbounded!(usize, i32, i64, i128); - - try_from_both_bounded!(isize, u8); + // Fallible across platfoms, only implementation differs try_from_lower_bounded!(isize, u16, u32, u64, u128); - try_from_both_bounded!(isize, i8); - try_from_unbounded!(isize, i16, i32, i64, i128); - - 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_upper_bounded, isize, u16, u32, u64, u128); - rev!(try_from_both_bounded, isize, i32, i64, i128); } #[cfg(target_pointer_width = "32")] @@ -3817,25 +3795,11 @@ mod ptr_try_from_impls { use super::TryFromIntError; use convert::TryFrom; - try_from_upper_bounded!(usize, u8, u16); - try_from_unbounded!(usize, u32, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32); - try_from_unbounded!(usize, i64, i128); - - try_from_both_bounded!(isize, u8, u16); + // Fallible across platfoms, only implementation differs + try_from_both_bounded!(isize, u16); try_from_lower_bounded!(isize, u32, u64, u128); - try_from_both_bounded!(isize, i8, i16); - try_from_unbounded!(isize, i32, i64, i128); - - rev!(try_from_unbounded, usize, 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, u16); - rev!(try_from_upper_bounded, isize, u32, u64, u128); - rev!(try_from_unbounded, isize, i32); - rev!(try_from_both_bounded, isize, i64, i128); } #[cfg(target_pointer_width = "64")] @@ -3843,25 +3807,11 @@ mod ptr_try_from_impls { use super::TryFromIntError; use convert::TryFrom; - try_from_upper_bounded!(usize, u8, u16, u32); - try_from_unbounded!(usize, u64, u128); - try_from_upper_bounded!(usize, i8, i16, i32, i64); - try_from_unbounded!(usize, i128); - - try_from_both_bounded!(isize, u8, u16, u32); + // Fallible across platfoms, only implementation differs + try_from_both_bounded!(isize, u16, u32); try_from_lower_bounded!(isize, u64, u128); - try_from_both_bounded!(isize, i8, i16, i32); - try_from_unbounded!(isize, i64, i128); - - rev!(try_from_unbounded, usize, 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, u16, u32); - rev!(try_from_upper_bounded, isize, u64, u128); - rev!(try_from_unbounded, isize, i32, i64); - rev!(try_from_both_bounded, isize, i128); } #[doc(hidden)] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 587dcbe6d6784..c7edb55b378c3 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -37,15 +37,6 @@ 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 { @@ -318,42 +309,6 @@ assume_usize_width! { 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_usizeu16, usize, u16 } - test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 } - 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_isizei32, isize, i32 } - test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } - } - - #[cfg(target_pointer_width = "32")] { - test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } - 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 } - test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } - } - - #[cfg(target_pointer_width = "64")] { - test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } - test_impl_try_from_always_ok! { test_try_u32usize, u32, usize } - test_impl_try_from_always_ok! { test_try_u32isize, u32, isize } - 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 } - } - ); } /// Conversions where max of $source can be represented as $target, @@ -402,24 +357,6 @@ assume_usize_width! { 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, @@ -461,29 +398,9 @@ 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_u16isize, u16, isize } - test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, 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. @@ -543,34 +460,6 @@ 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 } - } - ); } /// Conversions where neither the min nor the max of $source can be represented by @@ -615,22 +504,6 @@ 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 { diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 76bcb5fedc94a..2673f3ccfa3ab 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -10,7 +10,6 @@ use io::prelude::*; -use core::convert::TryInto; use cmp; use io::{self, Initializer, SeekFrom, Error, ErrorKind}; @@ -260,9 +259,26 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result Result { + if n <= (::max_value() as u64) { + Ok(n as usize) + } else { + Err(()) + } +} + +#[cfg(any(target_pointer_width = "64"))] +fn try_into(n: u64) -> Result { + Ok(n as usize) +} + // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { - let pos: usize = (*pos_mut).try_into().map_err(|_| { + let pos: usize = try_into(*pos_mut).map_err(|_| { Error::new(ErrorKind::InvalidInput, "cursor position exceeds maximum possible vector length") })?;