diff options
| author | kennytm <kennytm@gmail.com> | 2018-03-28 03:03:39 +0800 |
|---|---|---|
| committer | kennytm <kennytm@gmail.com> | 2018-03-28 03:03:39 +0800 |
| commit | 605ea7c31f7341995c2d1ae12b4b33fe6bd908b5 (patch) | |
| tree | 19b13ac2494f1e1b347ee8aae9c48150677434f3 | |
| parent | 19fe9d1181bb15f76cdf2b5335edff5a82c5152b (diff) | |
| parent | f513fbdf36ad0708fb222b8d55bc086dd4be18cf (diff) | |
| download | rust-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
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 | ^^^^^^^^^^^^^^^^^^^^^ |
