From 80e3f8941d86bad0bd8d5551e6d066741ade1fc2 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Tue, 29 Aug 2017 22:13:21 -0700 Subject: [PATCH] Add blanket TryFrom impl when From is implemented. Adds `impl TryFrom for U where U: From`. Removes `impl<'a, T> TryFrom<&'a str> for T where T: FromStr` due to overlapping impls caused by the new blanket impl. This removal is to be discussed further on the tracking issue for TryFrom. Refs #33417. --- src/libcore/convert.rs | 41 +++++++++++++++++++++++++++------------ src/libcore/iter/range.rs | 2 ++ src/libcore/num/mod.rs | 36 +++++++++------------------------- src/libcore/str/mod.rs | 7 ++----- 4 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 6f3c3863fae1..37b5bfa265d5 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -48,7 +48,24 @@ #![stable(feature = "rust1", since = "1.0.0")] -use str::FromStr; +use fmt; + +/// An uninhabited type used as the error type for implementations of fallible +/// conversion traits in cases where they cannot actually fail. +/// +/// Because `Infallible` has no constructors (variants), a value of this type +/// can never exist. It is used only to satisfy trait signatures that expect +/// an error type, and signals to both the compiler and the user that the error +/// case is impossible. +#[unstable(feature = "try_from", issue = "33417")] +pub enum Infallible {} + +#[unstable(feature = "try_from", issue = "33417")] +impl fmt::Debug for Infallible { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + match *self {} + } +} /// A cheap reference-to-reference conversion. Used to convert a value to a /// reference value within generic code. @@ -417,6 +434,17 @@ impl TryInto for T where U: TryFrom } } +// Infallible conversions are semantically equivalent to fallible conversions +// with an uninhabited error type. +#[unstable(feature = "try_from", issue = "33417")] +impl TryFrom for T where T: From { + type Error = Infallible; + + fn try_from(value: U) -> Result { + Ok(T::from(value)) + } +} + //////////////////////////////////////////////////////////////////////////////// // CONCRETE IMPLS //////////////////////////////////////////////////////////////////////////////// @@ -442,14 +470,3 @@ impl AsRef for str { self } } - -// FromStr implies TryFrom<&str> -#[unstable(feature = "try_from", issue = "33417")] -impl<'a, T> TryFrom<&'a str> for T where T: FromStr -{ - type Error = ::Err; - - fn try_from(s: &'a str) -> Result { - FromStr::from_str(s) - } -} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 73d518b570a1..e9aee4a4676d 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { match <$t>::try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), @@ -120,6 +121,7 @@ macro_rules! step_impl_signed { } #[inline] + #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { match <$unsigned>::try_from(n) { Ok(n_as_unsigned) => { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c5175287ccfa..4777f9d72ccd 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2507,12 +2507,10 @@ impl fmt::Display for TryFromIntError { macro_rules! try_from_unbounded { ($source:ty, $($target:ty),*) => {$( #[unstable(feature = "try_from", issue = "33417")] - impl TryFrom<$source> for $target { - type Error = TryFromIntError; - + impl From<$source> for $target { #[inline] - fn try_from(u: $source) -> Result<$target, TryFromIntError> { - Ok(u as $target) + fn from(value: $source) -> $target { + value as $target } } )*} @@ -2584,31 +2582,17 @@ macro_rules! rev { } /// intra-sign conversions -try_from_unbounded!(u8, u8, u16, u32, u64, u128); -try_from_unbounded!(u16, u16, u32, u64, u128); -try_from_unbounded!(u32, u32, u64, u128); -try_from_unbounded!(u64, u64, u128); -try_from_unbounded!(u128, u128); try_from_upper_bounded!(u16, u8); try_from_upper_bounded!(u32, u16, u8); try_from_upper_bounded!(u64, u32, u16, u8); try_from_upper_bounded!(u128, u64, u32, u16, u8); -try_from_unbounded!(i8, i8, i16, i32, i64, i128); -try_from_unbounded!(i16, i16, i32, i64, i128); -try_from_unbounded!(i32, i32, i64, i128); -try_from_unbounded!(i64, i64, i128); -try_from_unbounded!(i128, i128); try_from_both_bounded!(i16, i8); try_from_both_bounded!(i32, i16, i8); try_from_both_bounded!(i64, i32, i16, i8); try_from_both_bounded!(i128, i64, i32, i16, i8); // unsigned-to-signed -try_from_unbounded!(u8, i16, i32, i64, i128); -try_from_unbounded!(u16, i32, i64, i128); -try_from_unbounded!(u32, i64, i128); -try_from_unbounded!(u64, i128); try_from_upper_bounded!(u8, i8); try_from_upper_bounded!(u16, i8, i16); try_from_upper_bounded!(u32, i8, i16, i32); @@ -2627,10 +2611,8 @@ try_from_both_bounded!(i64, u32, u16, u8); try_from_both_bounded!(i128, u64, u32, u16, u8); // usize/isize -try_from_unbounded!(usize, usize); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); -try_from_unbounded!(isize, isize); #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { @@ -2647,14 +2629,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8); try_from_unbounded!(isize, i16, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16); + 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, i8, i16); + rev!(try_from_unbounded, isize, i16); rev!(try_from_both_bounded, isize, i32, i64, i128); } @@ -2673,14 +2655,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16); try_from_unbounded!(isize, i32, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32); + 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, i8, i16, i32); + rev!(try_from_unbounded, isize, i16, i32); rev!(try_from_both_bounded, isize, i64, i128); } @@ -2699,14 +2681,14 @@ mod ptr_try_from_impls { try_from_both_bounded!(isize, i8, i16, i32); try_from_unbounded!(isize, i64, i128); - rev!(try_from_unbounded, usize, u8, u16, u32, u64); + 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, i8, i16, i32, i64); + rev!(try_from_unbounded, isize, i16, i32, i64); rev!(try_from_both_bounded, isize, i128); } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a5f6e49a53b4..86a3b9f330bb 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -18,7 +18,6 @@ use self::pattern::Pattern; use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use char; -use convert::TryFrom; use fmt; use iter::{Map, Cloned, FusedIterator}; use slice::{self, SliceIndex}; @@ -2142,7 +2141,7 @@ pub trait StrExt { #[stable(feature = "core", since = "1.6.0")] fn is_empty(&self) -> bool; #[stable(feature = "core", since = "1.6.0")] - fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result; + fn parse(&self) -> Result; } // truncate `&str` to length at most equal to `max` @@ -2462,9 +2461,7 @@ impl StrExt for str { fn is_empty(&self) -> bool { self.len() == 0 } #[inline] - fn parse<'a, T>(&'a self) -> Result where T: TryFrom<&'a str> { - T::try_from(self) - } + fn parse(&self) -> Result { FromStr::from_str(self) } } #[stable(feature = "rust1", since = "1.0.0")]