about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-03-28 03:03:39 +0800
committerkennytm <kennytm@gmail.com>2018-03-28 03:03:39 +0800
commit605ea7c31f7341995c2d1ae12b4b33fe6bd908b5 (patch)
tree19b13ac2494f1e1b347ee8aae9c48150677434f3
parent19fe9d1181bb15f76cdf2b5335edff5a82c5152b (diff)
parentf513fbdf36ad0708fb222b8d55bc086dd4be18cf (diff)
downloadrust-605ea7c31f7341995c2d1ae12b4b33fe6bd908b5.tar.gz
rust-605ea7c31f7341995c2d1ae12b4b33fe6bd908b5.zip
Rollup merge of #49426 - lukaslueg:patch-1, r=kennytm
Update CONTRIBUTING.md

The current link is a 404, just link to the main repo page
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--src/libcore/array.rs6
-rw-r--r--src/libcore/char.rs6
-rw-r--r--src/libcore/convert.rs12
-rw-r--r--src/libcore/iter/range.rs74
-rw-r--r--src/libcore/num/mod.rs99
-rw-r--r--src/libcore/prelude/v1.rs3
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/num/mod.rs127
-rw-r--r--src/librustc/infer/outlives/bounds.rs2
-rw-r--r--src/librustc/traits/engine.rs71
-rw-r--r--src/librustc/traits/fulfill.rs149
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/specialize/mod.rs2
-rw-r--r--src/librustc/traits/trans/mod.rs3
-rw-r--r--src/librustc_apfloat/lib.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_traits/util.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs10
-rw-r--r--src/librustc_typeck/coherence/builtin.rs56
-rw-r--r--src/librustc_typeck/lib.rs5
-rw-r--r--src/libstd/error.rs6
-rw-r--r--src/libstd/io/cursor.rs20
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/prelude/v1.rs2
-rw-r--r--src/libstd_unicode/char.rs2
-rw-r--r--src/libstd_unicode/lib.rs1
-rw-r--r--src/test/ui/e0119/conflict-with-std.rs2
-rw-r--r--src/test/ui/e0119/conflict-with-std.stderr6
31 files changed, 344 insertions, 342 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2b389888e51..7a62405f059 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -594,7 +594,7 @@ If you're looking for somewhere to start, check out the [E-easy][eeasy] tag.
 [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated
 [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
 [lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
-[rfcbot]: https://github.com/dikaiosune/rust-dashboard/blob/master/RFCBOT.md
+[rfcbot]: https://github.com/anp/rfcbot-rs/
 
 ## Out-of-tree Contributions
 [out-of-tree-contributions]: #out-of-tree-contributions
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 3d24f8902bd..87144c27c9e 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 1638f9710f5..bbeebf52a73 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 7324df95bc5..63721395784 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/iter/range.rs b/src/libcore/iter/range.rs
index 8d1080bb876..72b48b56571 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 a5ba0bcdf7e..ee041e1e4f1 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,39 +3662,24 @@ 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
     }
 }
 
-// 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 = !;
-
-            #[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),*) => {$(
-        #[unstable(feature = "try_from", issue = "33417")]
+        #[stable(feature = "try_from", since = "1.26.0")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -3713,7 +3698,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 +3717,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;
 
@@ -3789,30 +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_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);
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -3820,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, 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, i16, i32);
-    rev!(try_from_both_bounded, isize, i64, i128);
 }
 
 #[cfg(target_pointer_width = "64")]
@@ -3846,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, 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, i16, i32, i64);
-    rev!(try_from_both_bounded, isize, i128);
 }
 
 #[doc(hidden)]
@@ -4074,6 +4021,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.
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index d43496c387c..2c8e27abac9 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/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 0b70f692403..1a68f04532d 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/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index 587dcbe6d67..c7edb55b378 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/librustc/infer/outlives/bounds.rs b/src/librustc/infer/outlives/bounds.rs
index 8bb3f4158ff..4bc64acc763 100644
--- a/src/librustc/infer/outlives/bounds.rs
+++ b/src/librustc/infer/outlives/bounds.rs
@@ -11,7 +11,7 @@
 use infer::InferCtxt;
 use syntax::ast;
 use syntax::codemap::Span;
-use traits::FulfillmentContext;
+use traits::{FulfillmentContext, TraitEngine};
 use ty::{self, Ty, TypeFoldable};
 use ty::outlives::Component;
 use ty::wf;
diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs
new file mode 100644
index 00000000000..8eee6f35ab9
--- /dev/null
+++ b/src/librustc/traits/engine.rs
@@ -0,0 +1,71 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use infer::InferCtxt;
+use ty::{self, Ty, TyCtxt};
+use hir::def_id::DefId;
+
+use super::{FulfillmentContext, FulfillmentError};
+use super::{ObligationCause, PendingPredicateObligation, PredicateObligation};
+
+pub trait TraitEngine<'tcx>: 'tcx {
+    fn normalize_projection_type<'a, 'gcx>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        projection_ty: ty::ProjectionTy<'tcx>,
+        cause: ObligationCause<'tcx>,
+    ) -> Ty<'tcx>;
+
+    fn register_bound<'a, 'gcx>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+        def_id: DefId,
+        cause: ObligationCause<'tcx>,
+    );
+
+    fn register_predicate_obligation<'a, 'gcx>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+        obligation: PredicateObligation<'tcx>,
+    );
+
+    fn select_all_or_error<'a, 'gcx>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+
+    fn select_where_possible<'a, 'gcx>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    ) -> Result<(), Vec<FulfillmentError<'tcx>>>;
+
+    fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>>;
+}
+
+impl<'a, 'gcx, 'tcx> dyn TraitEngine<'tcx> {
+    pub fn new(_tcx: TyCtxt<'_, '_, 'tcx>) -> Box<Self> {
+        Box::new(FulfillmentContext::new())
+    }
+
+    pub fn register_predicate_obligations<I>(
+        &mut self,
+        infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+        obligations: I,
+    ) where
+        I: IntoIterator<Item = PredicateObligation<'tcx>>,
+    {
+        for obligation in obligations {
+            self.register_predicate_obligation(infcx, obligation);
+        }
+    }
+}
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 150a2ead9e9..1c091d68a2e 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -21,6 +21,7 @@ use middle::const_val::{ConstEvalErr, ErrKind};
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
+use super::engine::TraitEngine;
 use super::{FulfillmentError, FulfillmentErrorCode};
 use super::{ObligationCause, PredicateObligation, Obligation};
 use super::project;
@@ -85,6 +86,59 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
         }
     }
 
+    pub fn register_predicate_obligations<I>(&mut self,
+                                             infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                             obligations: I)
+        where I: IntoIterator<Item = PredicateObligation<'tcx>>
+    {
+        for obligation in obligations {
+            self.register_predicate_obligation(infcx, obligation);
+        }
+    }
+
+    /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
+    /// only attempts to select obligations that haven't been seen before.
+    fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
+              -> Result<(),Vec<FulfillmentError<'tcx>>> {
+        debug!("select(obligation-forest-size={})", self.predicates.len());
+
+        let mut errors = Vec::new();
+
+        loop {
+            debug!("select: starting another iteration");
+
+            // Process pending obligations.
+            let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
+                selcx,
+                register_region_obligations: self.register_region_obligations
+            });
+            debug!("select: outcome={:?}", outcome);
+
+            // FIXME: if we kept the original cache key, we could mark projection
+            // obligations as complete for the projection cache here.
+
+            errors.extend(
+                outcome.errors.into_iter()
+                              .map(|e| to_fulfillment_error(e)));
+
+            // If nothing new was added, no need to keep looping.
+            if outcome.stalled {
+                break;
+            }
+        }
+
+        debug!("select({} predicates remaining, {} errors) done",
+               self.predicates.len(), errors.len());
+
+        if errors.is_empty() {
+            Ok(())
+        } else {
+            Err(errors)
+        }
+    }
+}
+
+impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
     /// creating a fresh type variable `$0` as well as a projection
     /// predicate `<SomeType as SomeTrait>::X == $0`. When the
@@ -92,12 +146,12 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
     /// `SomeTrait` or a where clause that lets us unify `$0` with
     /// something concrete. If this fails, we'll unify `$0` with
     /// `projection_ty` again.
-    pub fn normalize_projection_type(&mut self,
-                                     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                     param_env: ty::ParamEnv<'tcx>,
-                                     projection_ty: ty::ProjectionTy<'tcx>,
-                                     cause: ObligationCause<'tcx>)
-                                     -> Ty<'tcx>
+    fn normalize_projection_type<'a, 'gcx>(&mut self,
+                                 infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                 param_env: ty::ParamEnv<'tcx>,
+                                 projection_ty: ty::ProjectionTy<'tcx>,
+                                 cause: ObligationCause<'tcx>)
+                                 -> Ty<'tcx>
     {
         debug!("normalize_projection_type(projection_ty={:?})",
                projection_ty);
@@ -125,12 +179,12 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
     /// Requires that `ty` must implement the trait with `def_id` in
     /// the given environment. This trait must not have any type
     /// parameters (except for `Self`).
-    pub fn register_bound(&mut self,
-                          infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                          param_env: ty::ParamEnv<'tcx>,
-                          ty: Ty<'tcx>,
-                          def_id: DefId,
-                          cause: ObligationCause<'tcx>)
+    fn register_bound<'a, 'gcx>(&mut self,
+                      infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                      param_env: ty::ParamEnv<'tcx>,
+                      ty: Ty<'tcx>,
+                      def_id: DefId,
+                      cause: ObligationCause<'tcx>)
     {
         let trait_ref = ty::TraitRef {
             def_id,
@@ -144,9 +198,9 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
         });
     }
 
-    pub fn register_predicate_obligation(&mut self,
-                                         infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                         obligation: PredicateObligation<'tcx>)
+    fn register_predicate_obligation<'a, 'gcx>(&mut self,
+                                     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                     obligation: PredicateObligation<'tcx>)
     {
         // this helps to reduce duplicate errors, as well as making
         // debug output much nicer to read and so on.
@@ -162,19 +216,9 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
         });
     }
 
-    pub fn register_predicate_obligations<I>(&mut self,
-                                             infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                             obligations: I)
-        where I: IntoIterator<Item = PredicateObligation<'tcx>>
-    {
-        for obligation in obligations {
-            self.register_predicate_obligation(infcx, obligation);
-        }
-    }
-
-    pub fn select_all_or_error(&mut self,
-                               infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                               -> Result<(),Vec<FulfillmentError<'tcx>>>
+    fn select_all_or_error<'a, 'gcx>(&mut self,
+                                     infcx: &InferCtxt<'a, 'gcx, 'tcx>)
+                                     -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         self.select_where_possible(infcx)?;
 
@@ -190,58 +234,17 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
         }
     }
 
-    pub fn select_where_possible(&mut self,
-                                 infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                                 -> Result<(),Vec<FulfillmentError<'tcx>>>
+    fn select_where_possible<'a, 'gcx>(&mut self,
+                             infcx: &InferCtxt<'a, 'gcx, 'tcx>)
+                             -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         let mut selcx = SelectionContext::new(infcx);
         self.select(&mut selcx)
     }
 
-    pub fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
+    fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
         self.predicates.pending_obligations()
     }
-
-    /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
-    /// only attempts to select obligations that haven't been seen before.
-    fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
-              -> Result<(),Vec<FulfillmentError<'tcx>>> {
-        debug!("select(obligation-forest-size={})", self.predicates.len());
-
-        let mut errors = Vec::new();
-
-        loop {
-            debug!("select: starting another iteration");
-
-            // Process pending obligations.
-            let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
-                selcx,
-                register_region_obligations: self.register_region_obligations
-            });
-            debug!("select: outcome={:?}", outcome);
-
-            // FIXME: if we kept the original cache key, we could mark projection
-            // obligations as complete for the projection cache here.
-
-            errors.extend(
-                outcome.errors.into_iter()
-                              .map(|e| to_fulfillment_error(e)));
-
-            // If nothing new was added, no need to keep looping.
-            if outcome.stalled {
-                break;
-            }
-        }
-
-        debug!("select({} predicates remaining, {} errors) done",
-               self.predicates.len(), errors.len());
-
-        if errors.is_empty() {
-            Ok(())
-        } else {
-            Err(errors)
-        }
-    }
 }
 
 struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index a0ba88f7d55..1d5d3e41c9c 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -34,7 +34,7 @@ use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
 pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult};
-pub use self::fulfill::FulfillmentContext;
+pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};
 pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized};
@@ -45,6 +45,7 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
 pub use self::select::IntercrateAmbiguityCause;
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::{SpecializesCache, find_associated_item};
+pub use self::engine::TraitEngine;
 pub use self::util::elaborate_predicates;
 pub use self::util::supertraits;
 pub use self::util::Supertraits;
@@ -54,6 +55,7 @@ pub use self::util::transitive_bounds;
 
 mod coherence;
 pub mod error_reporting;
+mod engine;
 mod fulfill;
 mod project;
 mod object_safety;
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 5ea089abb8e..a9d1c8bcc3d 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use ty::subst::{Subst, Substs};
-use traits::{self, ObligationCause};
+use traits::{self, ObligationCause, TraitEngine};
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, TyCtxt, TypeFoldable};
 use syntax_pos::DUMMY_SP;
diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs
index cc8b74e0ee2..31e851126d7 100644
--- a/src/librustc/traits/trans/mod.rs
+++ b/src/librustc/traits/trans/mod.rs
@@ -18,7 +18,8 @@ use std::marker::PhantomData;
 use syntax_pos::DUMMY_SP;
 use infer::InferCtxt;
 use syntax_pos::Span;
-use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable};
+use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext,
+             TraitEngine, Vtable};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::{Subst, Substs};
 use ty::fold::TypeFoldable;
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index 2ee7bea8476..6f08fcf7025 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/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 80a439b1830..544cb5eefc8 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -20,7 +20,7 @@ use dataflow::move_paths::MoveData;
 use rustc::hir::def_id::DefId;
 use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
 use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
-use rustc::traits::{self, Normalized, FulfillmentContext};
+use rustc::traits::{self, Normalized, TraitEngine};
 use rustc::traits::query::NoSolution;
 use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
@@ -662,7 +662,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     where
         OP: FnOnce(&mut Self) -> InferResult<'tcx, R>,
     {
-        let mut fulfill_cx = FulfillmentContext::new();
+        let mut fulfill_cx = TraitEngine::new(self.infcx.tcx);
         let InferOk { value, obligations } = self.infcx.commit_if_ok(|_| op(self))?;
         fulfill_cx.register_predicate_obligations(self.infcx, obligations);
         if let Err(e) = fulfill_cx.select_all_or_error(self.infcx) {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 8e2f98d2769..aeefd5ab1d5 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -21,7 +21,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
-use rustc::traits;
+use rustc::traits::{self, TraitEngine};
 use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
 use rustc::ty::cast::CastTy;
 use rustc::ty::maps::Providers;
diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs
index 976eb442a0d..bff070ab73d 100644
--- a/src/librustc_traits/util.rs
+++ b/src/librustc_traits/util.rs
@@ -12,7 +12,7 @@ use rustc::infer::InferCtxt;
 use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints,
                               QueryResult};
 use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc::traits::FulfillmentContext;
+use rustc::traits::{FulfillmentContext, TraitEngine};
 use rustc::traits::query::NoSolution;
 use rustc::ty;
 use std::fmt::Debug;
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 596381d7ea6..d508b6df924 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -16,7 +16,7 @@ use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::middle::region;
 use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::traits::{self, ObligationCause};
+use rustc::traits::{ObligationCause, TraitEngine};
 use util::common::ErrorReported;
 
 use syntax::ast;
@@ -84,7 +84,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
     tcx.infer_ctxt().enter(|ref infcx| {
         let impl_param_env = tcx.param_env(self_type_did);
         let tcx = infcx.tcx;
-        let mut fulfillment_cx = traits::FulfillmentContext::new();
+        let mut fulfillment_cx = TraitEngine::new(tcx);
 
         let named_type = tcx.type_of(self_type_did);
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f820b0ba16b..0f0f59c28f8 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -95,7 +95,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
 use rustc::mir::interpret::{GlobalId};
 use rustc::ty::subst::{Kind, Subst, Substs};
-use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
+use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
 use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
@@ -195,7 +195,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     locals: RefCell<NodeMap<Ty<'tcx>>>,
 
-    fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+    fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
 
     // When we process a call like `c()` where `c` is a closure type,
     // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
@@ -634,7 +634,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
                 maybe_tables: infcx.in_progress_tables,
             },
             infcx,
-            fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
+            fulfillment_cx: RefCell::new(TraitEngine::new(tcx)),
             locals: RefCell::new(NodeMap()),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
@@ -2910,7 +2910,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // is polymorphic) and the expected return type.
                 // No argument expectations are produced if unification fails.
                 let origin = self.misc(call_span);
-                let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
+                let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret);
 
                 // FIXME(#27336) can't use ? here, Try::from_error doesn't default
                 // to identity so the resulting type is not constrained.
@@ -2921,7 +2921,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
                         self.save_and_restore_in_snapshot_flag(|_| {
-                            let mut fulfill = FulfillmentContext::new();
+                            let mut fulfill = TraitEngine::new(self.tcx);
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 9493c36fe95..aa4322783c6 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -15,7 +15,7 @@ use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::middle::region;
 use rustc::middle::lang_items::UnsizeTraitLangItem;
 
-use rustc::traits::{self, ObligationCause};
+use rustc::traits::{self, TraitEngine, ObligationCause};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::TypeFoldable;
 use rustc::ty::adjustment::CoerceUnsizedInfo;
@@ -172,34 +172,34 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                      impl_did: DefId)
                                      -> CoerceUnsizedInfo {
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
-    let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap();
+    let coerce_unsized_trait = gcx.lang_items().coerce_unsized_trait().unwrap();
 
-    let unsize_trait = match tcx.lang_items().require(UnsizeTraitLangItem) {
+    let unsize_trait = match gcx.lang_items().require(UnsizeTraitLangItem) {
         Ok(id) => id,
         Err(err) => {
-            tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
+            gcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
         }
     };
 
     // this provider should only get invoked for local def-ids
-    let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
+    let impl_node_id = gcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
         bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
     });
 
-    let source = tcx.type_of(impl_did);
-    let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+    let source = gcx.type_of(impl_did);
+    let trait_ref = gcx.impl_trait_ref(impl_did).unwrap();
     assert_eq!(trait_ref.def_id, coerce_unsized_trait);
     let target = trait_ref.substs.type_at(1);
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)",
            source,
            target);
 
-    let span = tcx.hir.span(impl_node_id);
-    let param_env = tcx.param_env(impl_did);
+    let span = gcx.hir.span(impl_node_id);
+    let param_env = gcx.param_env(impl_did);
     assert!(!source.has_escaping_regions());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
@@ -208,11 +208,11 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            source,
            target);
 
-    tcx.infer_ctxt().enter(|infcx| {
+    gcx.infer_ctxt().enter(|infcx| {
         let cause = ObligationCause::misc(span, impl_node_id);
-        let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
-                           mt_b: ty::TypeAndMut<'tcx>,
-                           mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
+        let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>,
+                           mt_b: ty::TypeAndMut<'gcx>,
+                           mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| {
             if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) {
                 infcx.report_mismatched_types(&cause,
                                              mk_ptr(mt_b.ty),
@@ -225,20 +225,20 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) {
             (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
                 infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
-                check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
+                check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ref(r_b, ty))
             }
 
             (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
             (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
-                check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
+                check_mutbl(mt_a, mt_b, &|ty| gcx.mk_imm_ptr(ty))
             }
 
             (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) if def_a.is_struct() &&
                                                                           def_b.is_struct() => {
                 if def_a != def_b {
-                    let source_path = tcx.item_path_str(def_a.did);
-                    let target_path = tcx.item_path_str(def_b.did);
-                    span_err!(tcx.sess,
+                    let source_path = gcx.item_path_str(def_a.did);
+                    let target_path = gcx.item_path_str(def_b.did);
+                    span_err!(gcx.sess,
                               span,
                               E0377,
                               "the trait `CoerceUnsized` may only be implemented \
@@ -292,9 +292,9 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 let diff_fields = fields.iter()
                     .enumerate()
                     .filter_map(|(i, f)| {
-                        let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
+                        let (a, b) = (f.ty(gcx, substs_a), f.ty(gcx, substs_b));
 
-                        if tcx.type_of(f.did).is_phantom_data() {
+                        if gcx.type_of(f.did).is_phantom_data() {
                             // Ignore PhantomData fields
                             return None;
                         }
@@ -321,7 +321,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     .collect::<Vec<_>>();
 
                 if diff_fields.is_empty() {
-                    span_err!(tcx.sess,
+                    span_err!(gcx.sess,
                               span,
                               E0374,
                               "the trait `CoerceUnsized` may only be implemented \
@@ -329,14 +329,14 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                being coerced, none found");
                     return err_info;
                 } else if diff_fields.len() > 1 {
-                    let item = tcx.hir.expect_item(impl_node_id);
+                    let item = gcx.hir.expect_item(impl_node_id);
                     let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
                         t.path.span
                     } else {
-                        tcx.hir.span(impl_node_id)
+                        gcx.hir.span(impl_node_id)
                     };
 
-                    let mut err = struct_span_err!(tcx.sess,
+                    let mut err = struct_span_err!(gcx.sess,
                                                    span,
                                                    E0375,
                                                    "implementing the trait \
@@ -363,7 +363,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             _ => {
-                span_err!(tcx.sess,
+                span_err!(gcx.sess,
                           span,
                           E0376,
                           "the trait `CoerceUnsized` may only be implemented \
@@ -372,11 +372,11 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         };
 
-        let mut fulfill_cx = traits::FulfillmentContext::new();
+        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
 
         // Register an obligation for `A: Trait<B>`.
         let cause = traits::ObligationCause::misc(span, impl_node_id);
-        let predicate = tcx.predicate_for_trait_def(param_env,
+        let predicate = gcx.predicate_for_trait_def(param_env,
                                                     cause,
                                                     trait_def_id,
                                                     0,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8b3d5af3edd..86c5e49d167 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -88,6 +88,7 @@ This API is completely unstable and subject to change.
 #![feature(slice_patterns)]
 #![cfg_attr(stage0, feature(i128_type))]
 #![cfg_attr(stage0, feature(never_type))]
+#![feature(dyn_trait)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -111,7 +112,7 @@ use rustc::infer::InferOk;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
-use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode};
+use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine};
 use session::{CompileIncomplete, config};
 use util::common::time;
 
@@ -160,7 +161,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 -> bool {
     tcx.infer_ctxt().enter(|ref infcx| {
         let param_env = ty::ParamEnv::empty();
-        let mut fulfill_cx = FulfillmentContext::new();
+        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
         match infcx.at(&cause, param_env).eq(expected, actual) {
             Ok(InferOk { obligations, .. }) => {
                 fulfill_cx.register_predicate_obligations(infcx, obligations);
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 79bb6af168f..3d0c96585b5 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/io/cursor.rs b/src/libstd/io/cursor.rs
index 76bcb5fedc9..2673f3ccfa3 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")
     })?;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 93996868f16..15a22443b6a 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/prelude/v1.rs b/src/libstd/prelude/v1.rs
index feedd4e1abe..d5b7c68a3fa 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")]
diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs
index de8b46d5f1b..33e47ade8cb 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 f155b62e3cc..c22ea1671fa 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 ed9033ad53d..a9f747d09ec 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 e8b2c84c0df..417ff1de3f8 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
    | ^^^^^^^^^^^^^^^^^^^^^