Add blanket TryFrom impl when From is implemented.

Adds `impl<T, U> TryFrom<T> for U where U: From<T>`.

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.
This commit is contained in:
Jimmy Cuadra 2017-08-29 22:13:21 -07:00
parent c11f689d24
commit 80e3f8941d
4 changed files with 42 additions and 44 deletions

View file

@ -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<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")]
impl<T, U> TryFrom<U> for T where T: From<U> {
type Error = Infallible;
fn try_from(value: U) -> Result<Self, Self::Error> {
Ok(T::from(value))
}
}
////////////////////////////////////////////////////////////////////////////////
// CONCRETE IMPLS
////////////////////////////////////////////////////////////////////////////////
@ -442,14 +470,3 @@ impl AsRef<str> 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 = <T as FromStr>::Err;
fn try_from(s: &'a str) -> Result<T, Self::Error> {
FromStr::from_str(s)
}
}

View file

@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned {
}
#[inline]
#[allow(unreachable_patterns)]
fn add_usize(&self, n: usize) -> Option<Self> {
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<Self> {
match <$unsigned>::try_from(n) {
Ok(n_as_unsigned) => {

View file

@ -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);
}

View file

@ -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<T, T::Error>;
fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
}
// 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<T, T::Error> where T: TryFrom<&'a str> {
T::try_from(self)
}
fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
}
#[stable(feature = "rust1", since = "1.0.0")]