Skip to content

Commit b7041bf

Browse files
committed
Auto merge of #44174 - jimmycuadra:try-from-infallible, r=sfackler
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` (originally added in #40281) 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. /cc @sfackler, @scottmcm (thank you for the help!), and @aturon
2 parents 6f87d20 + 27d95d3 commit b7041bf

File tree

7 files changed

+71
-48
lines changed

7 files changed

+71
-48
lines changed

src/libcore/convert.rs

+29-12
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,25 @@
4848
4949
#![stable(feature = "rust1", since = "1.0.0")]
5050

51-
use str::FromStr;
51+
use fmt;
5252

53+
/// A type used as the error type for implementations of fallible conversion
54+
/// traits in cases where conversions cannot actually fail.
55+
///
56+
/// Because `Infallible` has no variants, a value of this type can never exist.
57+
/// It is used only to satisfy trait signatures that expect an error type, and
58+
/// signals to both the compiler and the user that the error case is impossible.
59+
#[unstable(feature = "try_from", issue = "33417")]
60+
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
61+
pub enum Infallible {}
62+
63+
#[unstable(feature = "try_from", issue = "33417")]
64+
impl fmt::Display for Infallible {
65+
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
66+
match *self {
67+
}
68+
}
69+
}
5370
/// A cheap reference-to-reference conversion. Used to convert a value to a
5471
/// reference value within generic code.
5572
///
@@ -417,6 +434,17 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
417434
}
418435
}
419436

437+
// Infallible conversions are semantically equivalent to fallible conversions
438+
// with an uninhabited error type.
439+
#[unstable(feature = "try_from", issue = "33417")]
440+
impl<T, U> TryFrom<U> for T where T: From<U> {
441+
type Error = Infallible;
442+
443+
fn try_from(value: U) -> Result<Self, Self::Error> {
444+
Ok(T::from(value))
445+
}
446+
}
447+
420448
////////////////////////////////////////////////////////////////////////////////
421449
// CONCRETE IMPLS
422450
////////////////////////////////////////////////////////////////////////////////
@@ -442,14 +470,3 @@ impl AsRef<str> for str {
442470
self
443471
}
444472
}
445-
446-
// FromStr implies TryFrom<&str>
447-
#[unstable(feature = "try_from", issue = "33417")]
448-
impl<'a, T> TryFrom<&'a str> for T where T: FromStr
449-
{
450-
type Error = <T as FromStr>::Err;
451-
452-
fn try_from(s: &'a str) -> Result<T, Self::Error> {
453-
FromStr::from_str(s)
454-
}
455-
}

src/libcore/iter/range.rs

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned {
8989
}
9090

9191
#[inline]
92+
#[allow(unreachable_patterns)]
9293
fn add_usize(&self, n: usize) -> Option<Self> {
9394
match <$t>::try_from(n) {
9495
Ok(n_as_t) => self.checked_add(n_as_t),
@@ -120,6 +121,7 @@ macro_rules! step_impl_signed {
120121
}
121122

122123
#[inline]
124+
#[allow(unreachable_patterns)]
123125
fn add_usize(&self, n: usize) -> Option<Self> {
124126
match <$unsigned>::try_from(n) {
125127
Ok(n_as_unsigned) => {

src/libcore/num/mod.rs

+21-29
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414

15-
use convert::TryFrom;
15+
use convert::{Infallible, TryFrom};
1616
use fmt;
1717
use intrinsics;
1818
use str::FromStr;
@@ -2507,16 +2507,24 @@ impl fmt::Display for TryFromIntError {
25072507
}
25082508
}
25092509

2510+
#[unstable(feature = "try_from", issue = "33417")]
2511+
impl From<Infallible> for TryFromIntError {
2512+
fn from(infallible: Infallible) -> TryFromIntError {
2513+
match infallible {
2514+
}
2515+
}
2516+
}
2517+
25102518
// no possible bounds violation
25112519
macro_rules! try_from_unbounded {
25122520
($source:ty, $($target:ty),*) => {$(
25132521
#[unstable(feature = "try_from", issue = "33417")]
25142522
impl TryFrom<$source> for $target {
2515-
type Error = TryFromIntError;
2523+
type Error = Infallible;
25162524

25172525
#[inline]
2518-
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
2519-
Ok(u as $target)
2526+
fn try_from(value: $source) -> Result<Self, Self::Error> {
2527+
Ok(value as $target)
25202528
}
25212529
}
25222530
)*}
@@ -2588,31 +2596,17 @@ macro_rules! rev {
25882596
}
25892597

25902598
/// intra-sign conversions
2591-
try_from_unbounded!(u8, u8, u16, u32, u64, u128);
2592-
try_from_unbounded!(u16, u16, u32, u64, u128);
2593-
try_from_unbounded!(u32, u32, u64, u128);
2594-
try_from_unbounded!(u64, u64, u128);
2595-
try_from_unbounded!(u128, u128);
25962599
try_from_upper_bounded!(u16, u8);
25972600
try_from_upper_bounded!(u32, u16, u8);
25982601
try_from_upper_bounded!(u64, u32, u16, u8);
25992602
try_from_upper_bounded!(u128, u64, u32, u16, u8);
26002603

2601-
try_from_unbounded!(i8, i8, i16, i32, i64, i128);
2602-
try_from_unbounded!(i16, i16, i32, i64, i128);
2603-
try_from_unbounded!(i32, i32, i64, i128);
2604-
try_from_unbounded!(i64, i64, i128);
2605-
try_from_unbounded!(i128, i128);
26062604
try_from_both_bounded!(i16, i8);
26072605
try_from_both_bounded!(i32, i16, i8);
26082606
try_from_both_bounded!(i64, i32, i16, i8);
26092607
try_from_both_bounded!(i128, i64, i32, i16, i8);
26102608

26112609
// unsigned-to-signed
2612-
try_from_unbounded!(u8, i16, i32, i64, i128);
2613-
try_from_unbounded!(u16, i32, i64, i128);
2614-
try_from_unbounded!(u32, i64, i128);
2615-
try_from_unbounded!(u64, i128);
26162610
try_from_upper_bounded!(u8, i8);
26172611
try_from_upper_bounded!(u16, i8, i16);
26182612
try_from_upper_bounded!(u32, i8, i16, i32);
@@ -2631,15 +2625,13 @@ try_from_both_bounded!(i64, u32, u16, u8);
26312625
try_from_both_bounded!(i128, u64, u32, u16, u8);
26322626

26332627
// usize/isize
2634-
try_from_unbounded!(usize, usize);
26352628
try_from_upper_bounded!(usize, isize);
26362629
try_from_lower_bounded!(isize, usize);
2637-
try_from_unbounded!(isize, isize);
26382630

26392631
#[cfg(target_pointer_width = "16")]
26402632
mod ptr_try_from_impls {
26412633
use super::TryFromIntError;
2642-
use convert::TryFrom;
2634+
use convert::{Infallible, TryFrom};
26432635

26442636
try_from_upper_bounded!(usize, u8);
26452637
try_from_unbounded!(usize, u16, u32, u64, u128);
@@ -2651,21 +2643,21 @@ mod ptr_try_from_impls {
26512643
try_from_both_bounded!(isize, i8);
26522644
try_from_unbounded!(isize, i16, i32, i64, i128);
26532645

2654-
rev!(try_from_unbounded, usize, u8, u16);
2646+
rev!(try_from_unbounded, usize, u16);
26552647
rev!(try_from_upper_bounded, usize, u32, u64, u128);
26562648
rev!(try_from_lower_bounded, usize, i8, i16);
26572649
rev!(try_from_both_bounded, usize, i32, i64, i128);
26582650

26592651
rev!(try_from_unbounded, isize, u8);
26602652
rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
2661-
rev!(try_from_unbounded, isize, i8, i16);
2653+
rev!(try_from_unbounded, isize, i16);
26622654
rev!(try_from_both_bounded, isize, i32, i64, i128);
26632655
}
26642656

26652657
#[cfg(target_pointer_width = "32")]
26662658
mod ptr_try_from_impls {
26672659
use super::TryFromIntError;
2668-
use convert::TryFrom;
2660+
use convert::{Infallible, TryFrom};
26692661

26702662
try_from_upper_bounded!(usize, u8, u16);
26712663
try_from_unbounded!(usize, u32, u64, u128);
@@ -2677,21 +2669,21 @@ mod ptr_try_from_impls {
26772669
try_from_both_bounded!(isize, i8, i16);
26782670
try_from_unbounded!(isize, i32, i64, i128);
26792671

2680-
rev!(try_from_unbounded, usize, u8, u16, u32);
2672+
rev!(try_from_unbounded, usize, u16, u32);
26812673
rev!(try_from_upper_bounded, usize, u64, u128);
26822674
rev!(try_from_lower_bounded, usize, i8, i16, i32);
26832675
rev!(try_from_both_bounded, usize, i64, i128);
26842676

26852677
rev!(try_from_unbounded, isize, u8, u16);
26862678
rev!(try_from_upper_bounded, isize, u32, u64, u128);
2687-
rev!(try_from_unbounded, isize, i8, i16, i32);
2679+
rev!(try_from_unbounded, isize, i16, i32);
26882680
rev!(try_from_both_bounded, isize, i64, i128);
26892681
}
26902682

26912683
#[cfg(target_pointer_width = "64")]
26922684
mod ptr_try_from_impls {
26932685
use super::TryFromIntError;
2694-
use convert::TryFrom;
2686+
use convert::{Infallible, TryFrom};
26952687

26962688
try_from_upper_bounded!(usize, u8, u16, u32);
26972689
try_from_unbounded!(usize, u64, u128);
@@ -2703,14 +2695,14 @@ mod ptr_try_from_impls {
27032695
try_from_both_bounded!(isize, i8, i16, i32);
27042696
try_from_unbounded!(isize, i64, i128);
27052697

2706-
rev!(try_from_unbounded, usize, u8, u16, u32, u64);
2698+
rev!(try_from_unbounded, usize, u16, u32, u64);
27072699
rev!(try_from_upper_bounded, usize, u128);
27082700
rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
27092701
rev!(try_from_both_bounded, usize, i128);
27102702

27112703
rev!(try_from_unbounded, isize, u8, u16, u32);
27122704
rev!(try_from_upper_bounded, isize, u64, u128);
2713-
rev!(try_from_unbounded, isize, i8, i16, i32, i64);
2705+
rev!(try_from_unbounded, isize, i16, i32, i64);
27142706
rev!(try_from_both_bounded, isize, i128);
27152707
}
27162708

src/libcore/str/mod.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use self::pattern::Pattern;
1818
use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
1919

2020
use char;
21-
use convert::TryFrom;
2221
use fmt;
2322
use iter::{Map, Cloned, FusedIterator, TrustedLen};
2423
use iter_private::TrustedRandomAccess;
@@ -2198,7 +2197,7 @@ pub trait StrExt {
21982197
#[stable(feature = "core", since = "1.6.0")]
21992198
fn is_empty(&self) -> bool;
22002199
#[stable(feature = "core", since = "1.6.0")]
2201-
fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result<T, T::Error>;
2200+
fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
22022201
}
22032202

22042203
// truncate `&str` to length at most equal to `max`
@@ -2518,9 +2517,7 @@ impl StrExt for str {
25182517
fn is_empty(&self) -> bool { self.len() == 0 }
25192518

25202519
#[inline]
2521-
fn parse<'a, T>(&'a self) -> Result<T, T::Error> where T: TryFrom<&'a str> {
2522-
T::try_from(self)
2523-
}
2520+
fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
25242521
}
25252522

25262523
#[stable(feature = "rust1", since = "1.0.0")]

src/libcore/tests/char.rs

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ fn test_convert() {
3232
#[test]
3333
fn test_from_str() {
3434
assert_eq!(char::from_str("a").unwrap(), 'a');
35-
assert_eq!(char::try_from("a").unwrap(), 'a');
3635
assert_eq!(char::from_str("\0").unwrap(), '\0');
3736
assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}');
3837
assert!(char::from_str("").is_err());

src/libcore/tests/num/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use core::convert::TryFrom;
11+
use core::convert::{TryFrom, TryInto};
1212
use core::cmp::PartialEq;
1313
use core::fmt::Debug;
1414
use core::marker::Copy;
15+
use core::num::TryFromIntError;
1516
use core::ops::{Add, Sub, Mul, Div, Rem};
1617
use core::option::Option;
1718
use core::option::Option::{Some, None};
@@ -134,6 +135,13 @@ fn test_empty() {
134135
assert_eq!("".parse::<u8>().ok(), None);
135136
}
136137

138+
#[test]
139+
fn test_infallible_try_from_int_error() {
140+
let func = |x: i8| -> Result<i32, TryFromIntError> { Ok(x.try_into()?) };
141+
142+
assert!(func(0).is_ok());
143+
}
144+
137145
macro_rules! test_impl_from {
138146
($fn_name: ident, $Small: ty, $Large: ty) => {
139147
#[test]

src/libstd/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ use any::TypeId;
5656
use borrow::Cow;
5757
use cell;
5858
use char;
59+
use convert;
5960
use fmt::{self, Debug, Display};
6061
use mem::transmute;
6162
use num;
@@ -362,6 +363,13 @@ impl Error for char::ParseCharError {
362363
}
363364
}
364365

366+
#[unstable(feature = "try_from", issue = "33417")]
367+
impl Error for convert::Infallible {
368+
fn description(&self) -> &str {
369+
match *self {
370+
}
371+
}
372+
}
365373

366374
// copied from any.rs
367375
impl Error + 'static {

0 commit comments

Comments
 (0)