From 2178ef8b220daec3228f6f4dae60787e506fa089 Mon Sep 17 00:00:00 2001
From: Simon Sapin <simon.sapin@exyr.org>
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 <simon.sapin@exyr.org>
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<Self, Self::Error> {

From e53a2a72743810e05f58c61c9d8a4c89b712ad2e Mon Sep 17 00:00:00 2001
From: Simon Sapin <simon.sapin@exyr.org>
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<T, A: Unsize<[T]>> FixedSizeArray<T> 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<u32> for char {
     type Error = CharTryFromError;
 
@@ -280,11 +280,11 @@ impl TryFrom<u32> 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<T>: 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<T>: 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<T, Self::Error>;
 }
 
 /// Attempt to construct `Self` via a conversion.
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
 pub trait TryFrom<T>: 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<Self, Self::Error>;
 }
 
@@ -405,7 +409,7 @@ impl<T> From<T> for T {
 
 
 // TryFrom implies TryInto
-#[unstable(feature = "try_from", issue = "33417")]
+#[stable(feature = "try_from", since = "1.26.0")]
 impl<T, U> TryInto<U> for T where U: TryFrom<T>
 {
     type Error = U::Error;
@@ -417,7 +421,7 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
 
 // 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<T, U> TryFrom<U> for T where T: From<U> {
     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<Q>` for type `std::boxed::Box<Q>`:
-  --> $DIR/conflict-with-std.rs:17:1
+  --> $DIR/conflict-with-std.rs:15:1
    |
 LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
              where T: ?Sized;
 
 error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`:
-  --> $DIR/conflict-with-std.rs:24:1
+  --> $DIR/conflict-with-std.rs:22:1
    |
 LL | impl From<S> for S { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | impl From<S> for S { //~ ERROR conflicting implementations
            - impl<T> std::convert::From<T> for T;
 
 error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`:
-  --> $DIR/conflict-with-std.rs:31:1
+  --> $DIR/conflict-with-std.rs:29:1
    |
 LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^

From 09008cc23ff6395c2c928f3690e07d7389d08ebc Mon Sep 17 00:00:00 2001
From: Simon Sapin <simon.sapin@exyr.org>
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 <simon.sapin@exyr.org>
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<Self> {
-                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<Self> {
-                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<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
+
+/// 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<Self, ()>;
+}
+
+impl<T> PrivateTryFromUsize for T where T: TryFrom<usize> {
+    #[inline]
+    fn private_try_from(n: usize) -> Result<Self, ()> {
+        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<Self, ()> {
+                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<Self, Self::Error> {
-                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<us
     Ok(amt)
 }
 
+/// Compensate removal of some impls per
+/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243
+#[cfg(any(target_pointer_width = "16",
+          target_pointer_width = "32"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+    if n <= (<usize>::max_value() as u64) {
+        Ok(n as usize)
+    } else {
+        Err(())
+    }
+}
+
+#[cfg(any(target_pointer_width = "64"))]
+fn try_into(n: u64) -> Result<usize, ()> {
+    Ok(n as usize)
+}
+
 // Resizing write implementation
 fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
-    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")
     })?;