Skip to content

Commit 00aae71

Browse files
committed
Auto merge of #58302 - SimonSapin:tryfrom, r=alexcrichton
Stabilize TryFrom and TryInto with a convert::Infallible empty enum This is the plan proposed in #33417 (comment)
2 parents b57fe74 + cf26754 commit 00aae71

File tree

16 files changed

+163
-79
lines changed

16 files changed

+163
-79
lines changed

src/liballoc/string.rs

+3-34
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ impl String {
486486
/// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html
487487
/// [`as_bytes`]: struct.String.html#method.as_bytes
488488
/// [`FromUtf8Error`]: struct.FromUtf8Error.html
489-
/// [`Err`]: ../../stdresult/enum.Result.html#variant.Err
489+
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
490490
#[inline]
491491
#[stable(feature = "rust1", since = "1.0.0")]
492492
pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
@@ -2073,48 +2073,17 @@ impl ops::DerefMut for String {
20732073
/// [`String`]: struct.String.html
20742074
/// [`from_str`]: ../../std/str/trait.FromStr.html#tymethod.from_str
20752075
#[stable(feature = "str_parse_error", since = "1.5.0")]
2076-
#[derive(Copy)]
2077-
pub enum ParseError {}
2076+
pub type ParseError = core::convert::Infallible;
20782077

20792078
#[stable(feature = "rust1", since = "1.0.0")]
20802079
impl FromStr for String {
2081-
type Err = ParseError;
2080+
type Err = core::convert::Infallible;
20822081
#[inline]
20832082
fn from_str(s: &str) -> Result<String, ParseError> {
20842083
Ok(String::from(s))
20852084
}
20862085
}
20872086

2088-
#[stable(feature = "str_parse_error", since = "1.5.0")]
2089-
impl Clone for ParseError {
2090-
fn clone(&self) -> ParseError {
2091-
match *self {}
2092-
}
2093-
}
2094-
2095-
#[stable(feature = "str_parse_error", since = "1.5.0")]
2096-
impl fmt::Debug for ParseError {
2097-
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
2098-
match *self {}
2099-
}
2100-
}
2101-
2102-
#[stable(feature = "str_parse_error2", since = "1.8.0")]
2103-
impl fmt::Display for ParseError {
2104-
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
2105-
match *self {}
2106-
}
2107-
}
2108-
2109-
#[stable(feature = "str_parse_error", since = "1.5.0")]
2110-
impl PartialEq for ParseError {
2111-
fn eq(&self, _: &ParseError) -> bool {
2112-
match *self {}
2113-
}
2114-
}
2115-
2116-
#[stable(feature = "str_parse_error", since = "1.5.0")]
2117-
impl Eq for ParseError {}
21182087

21192088
/// A trait for converting a value to a `String`.
21202089
///

src/libcore/array.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
4949
}
5050

5151
/// The error type returned when a conversion from a slice to an array fails.
52-
#[unstable(feature = "try_from", issue = "33417")]
52+
#[stable(feature = "try_from", since = "1.34.0")]
5353
#[derive(Debug, Copy, Clone)]
5454
pub struct TryFromSliceError(());
5555

@@ -138,7 +138,7 @@ macro_rules! array_impls {
138138
}
139139
}
140140

141-
#[unstable(feature = "try_from", issue = "33417")]
141+
#[stable(feature = "try_from", since = "1.34.0")]
142142
impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy {
143143
type Error = TryFromSliceError;
144144

@@ -147,7 +147,7 @@ macro_rules! array_impls {
147147
}
148148
}
149149

150-
#[unstable(feature = "try_from", issue = "33417")]
150+
#[stable(feature = "try_from", since = "1.34.0")]
151151
impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
152152
type Error = TryFromSliceError;
153153

@@ -161,7 +161,7 @@ macro_rules! array_impls {
161161
}
162162
}
163163

164-
#[unstable(feature = "try_from", issue = "33417")]
164+
#[stable(feature = "try_from", since = "1.34.0")]
165165
impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
166166
type Error = TryFromSliceError;
167167

src/libcore/char/convert.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl FromStr for char {
218218
}
219219

220220

221-
#[unstable(feature = "try_from", issue = "33417")]
221+
#[stable(feature = "try_from", since = "1.34.0")]
222222
impl TryFrom<u32> for char {
223223
type Error = CharTryFromError;
224224

@@ -233,11 +233,11 @@ impl TryFrom<u32> for char {
233233
}
234234

235235
/// The error type returned when a conversion from u32 to char fails.
236-
#[unstable(feature = "try_from", issue = "33417")]
236+
#[stable(feature = "try_from", since = "1.34.0")]
237237
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
238238
pub struct CharTryFromError(());
239239

240-
#[unstable(feature = "try_from", issue = "33417")]
240+
#[stable(feature = "try_from", since = "1.34.0")]
241241
impl fmt::Display for CharTryFromError {
242242
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243243
"converted integer out of range for `char`".fmt(f)

src/libcore/char/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub use self::convert::{from_u32, from_digit};
3030
pub use self::convert::from_u32_unchecked;
3131
#[stable(feature = "char_from_str", since = "1.20.0")]
3232
pub use self::convert::ParseCharError;
33-
#[unstable(feature = "try_from", issue = "33417")]
33+
#[stable(feature = "try_from", since = "1.34.0")]
3434
pub use self::convert::CharTryFromError;
3535
#[stable(feature = "decode_utf16", since = "1.9.0")]
3636
pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};

src/libcore/convert.rs

+123-5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
4242
#![stable(feature = "rust1", since = "1.0.0")]
4343

44+
use fmt;
45+
4446
/// An identity function.
4547
///
4648
/// Two things are important to note about this function:
@@ -367,22 +369,26 @@ pub trait From<T>: Sized {
367369
///
368370
/// [`TryFrom`]: trait.TryFrom.html
369371
/// [`Into`]: trait.Into.html
370-
#[unstable(feature = "try_from", issue = "33417")]
372+
#[stable(feature = "try_from", since = "1.34.0")]
371373
pub trait TryInto<T>: Sized {
372374
/// The type returned in the event of a conversion error.
375+
#[stable(feature = "try_from", since = "1.34.0")]
373376
type Error;
374377

375378
/// Performs the conversion.
379+
#[stable(feature = "try_from", since = "1.34.0")]
376380
fn try_into(self) -> Result<T, Self::Error>;
377381
}
378382

379383
/// Attempt to construct `Self` via a conversion.
380-
#[unstable(feature = "try_from", issue = "33417")]
384+
#[stable(feature = "try_from", since = "1.34.0")]
381385
pub trait TryFrom<T>: Sized {
382386
/// The type returned in the event of a conversion error.
387+
#[stable(feature = "try_from", since = "1.34.0")]
383388
type Error;
384389

385390
/// Performs the conversion.
391+
#[stable(feature = "try_from", since = "1.34.0")]
386392
fn try_from(value: T) -> Result<Self, Self::Error>;
387393
}
388394

@@ -450,7 +456,7 @@ impl<T> From<T> for T {
450456

451457

452458
// TryFrom implies TryInto
453-
#[unstable(feature = "try_from", issue = "33417")]
459+
#[stable(feature = "try_from", since = "1.34.0")]
454460
impl<T, U> TryInto<U> for T where U: TryFrom<T>
455461
{
456462
type Error = U::Error;
@@ -462,9 +468,9 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
462468

463469
// Infallible conversions are semantically equivalent to fallible conversions
464470
// with an uninhabited error type.
465-
#[unstable(feature = "try_from", issue = "33417")]
471+
#[stable(feature = "try_from", since = "1.34.0")]
466472
impl<T, U> TryFrom<U> for T where U: Into<T> {
467-
type Error = !;
473+
type Error = Infallible;
468474

469475
fn try_from(value: U) -> Result<Self, Self::Error> {
470476
Ok(U::into(value))
@@ -496,3 +502,115 @@ impl AsRef<str> for str {
496502
self
497503
}
498504
}
505+
506+
////////////////////////////////////////////////////////////////////////////////
507+
// THE NO-ERROR ERROR TYPE
508+
////////////////////////////////////////////////////////////////////////////////
509+
510+
/// The error type for errors that can never happen.
511+
///
512+
/// Since this enum has no variant, a value of this type can never actually exist.
513+
/// This can be useful for generic APIs that use [`Result`] and parameterize the error type,
514+
/// to indicate that the result is always [`Ok`].
515+
///
516+
/// For example, the [`TryFrom`] trait (conversion that returns a [`Result`])
517+
/// has a blanket implementation for all types where a reverse [`Into`] implementation exists.
518+
///
519+
/// ```ignore (illustrates std code, duplicating the impl in a doctest would be an error)
520+
/// impl<T, U> TryFrom<U> for T where U: Into<T> {
521+
/// type Error = Infallible;
522+
///
523+
/// fn try_from(value: U) -> Result<Self, Infallible> {
524+
/// Ok(U::into(value)) // Never returns `Err`
525+
/// }
526+
/// }
527+
/// ```
528+
///
529+
/// # Future compatibility
530+
///
531+
/// This enum has the same role as [the `!` “never” type][never],
532+
/// which is unstable in this version of Rust.
533+
/// When `!` is stabilized, we plan to make `Infallible` a type alias to it:
534+
///
535+
/// ```ignore (illustrates future std change)
536+
/// pub type Infallible = !;
537+
/// ```
538+
///
539+
/// … and eventually deprecate `Infallible`.
540+
///
541+
///
542+
/// However there is one case where `!` syntax can be used
543+
/// before `!` is stabilized as a full-fleged type: in the position of a function’s return type.
544+
/// Specifically, it is possible implementations for two different function pointer types:
545+
///
546+
/// ```
547+
/// trait MyTrait {}
548+
/// impl MyTrait for fn() -> ! {}
549+
/// impl MyTrait for fn() -> std::convert::Infallible {}
550+
/// ```
551+
///
552+
/// With `Infallible` being an enum, this code is valid.
553+
/// However when `Infallible` becomes an alias for the never type,
554+
/// the two `impl`s will start to overlap
555+
/// and therefore will be disallowed by the language’s trait coherence rules.
556+
///
557+
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
558+
/// [`Result`]: ../result/enum.Result.html
559+
/// [`TryFrom`]: trait.TryFrom.html
560+
/// [`Into`]: trait.Into.html
561+
/// [never]: ../../std/primitive.never.html
562+
#[stable(feature = "convert_infallible", since = "1.34.0")]
563+
#[derive(Copy)]
564+
pub enum Infallible {}
565+
566+
#[stable(feature = "convert_infallible", since = "1.34.0")]
567+
impl Clone for Infallible {
568+
fn clone(&self) -> Infallible {
569+
match *self {}
570+
}
571+
}
572+
573+
#[stable(feature = "convert_infallible", since = "1.34.0")]
574+
impl fmt::Debug for Infallible {
575+
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
576+
match *self {}
577+
}
578+
}
579+
580+
#[stable(feature = "convert_infallible", since = "1.34.0")]
581+
impl fmt::Display for Infallible {
582+
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
583+
match *self {}
584+
}
585+
}
586+
587+
#[stable(feature = "convert_infallible", since = "1.34.0")]
588+
impl PartialEq for Infallible {
589+
fn eq(&self, _: &Infallible) -> bool {
590+
match *self {}
591+
}
592+
}
593+
594+
#[stable(feature = "convert_infallible", since = "1.34.0")]
595+
impl Eq for Infallible {}
596+
597+
#[stable(feature = "convert_infallible", since = "1.34.0")]
598+
impl PartialOrd for Infallible {
599+
fn partial_cmp(&self, _other: &Self) -> Option<crate::cmp::Ordering> {
600+
match *self {}
601+
}
602+
}
603+
604+
#[stable(feature = "convert_infallible", since = "1.34.0")]
605+
impl Ord for Infallible {
606+
fn cmp(&self, _other: &Self) -> crate::cmp::Ordering {
607+
match *self {}
608+
}
609+
}
610+
611+
#[stable(feature = "convert_infallible", since = "1.34.0")]
612+
impl From<!> for Infallible {
613+
fn from(x: !) -> Self {
614+
x
615+
}
616+
}

0 commit comments

Comments
 (0)