New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for TryFrom/TryInto traits #33417

Open
alexcrichton opened this Issue May 4, 2016 · 168 comments

Comments

Projects
None yet
@alexcrichton
Member

alexcrichton commented May 4, 2016

Tracking issue for rust-lang/rfcs#1542

sfackler added a commit to sfackler/rust that referenced this issue May 5, 2016

sfackler added a commit to sfackler/rust that referenced this issue May 5, 2016

sfackler added a commit to sfackler/rust that referenced this issue May 7, 2016

Manishearth added a commit to Manishearth/rust that referenced this issue May 8, 2016

Manishearth added a commit to Manishearth/rust that referenced this issue May 8, 2016

Manishearth added a commit to Manishearth/rust that referenced this issue May 8, 2016

@Zoxc

This comment has been minimized.

Show comment
Hide comment
@Zoxc

Zoxc May 9, 2016

Contributor

Is there a way to generically print an error with the original value if the conversion fails without requiring Clone so a related method which panics on failure could have nice error messages?

Contributor

Zoxc commented May 9, 2016

Is there a way to generically print an error with the original value if the conversion fails without requiring Clone so a related method which panics on failure could have nice error messages?

@chris-morgan

This comment has been minimized.

Show comment
Hide comment
@chris-morgan

chris-morgan May 10, 2016

Member

A discussion of whether this should go in the prelude is pending for when this goes stable.

Member

chris-morgan commented May 10, 2016

A discussion of whether this should go in the prelude is pending for when this goes stable.

@shepmaster

This comment has been minimized.

Show comment
Hide comment
@shepmaster

shepmaster Jul 9, 2016

Member

Apologies if this is covered somewhere else, but what would we like to see before marking this as stable? I'm pretty sure I've reimplemented this functionality a few times in various projects, so a common reusable trait would make me 😄

Member

shepmaster commented Jul 9, 2016

Apologies if this is covered somewhere else, but what would we like to see before marking this as stable? I'm pretty sure I've reimplemented this functionality a few times in various projects, so a common reusable trait would make me 😄

@sfackler sfackler added the I-nominated label Jul 9, 2016

@sfackler

This comment has been minimized.

Show comment
Hide comment
@sfackler

sfackler Jul 9, 2016

Member

We can bring it up for discussion for the next cycle.

Member

sfackler commented Jul 9, 2016

We can bring it up for discussion for the next cycle.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 13, 2016

Member

🔔 This issue is now entering a cycle-long final comment period for stabilization 🔔

As a point of stabilization, the libs team would also like to add these traits to the prelude as part of their stabilization. This will require a crater run being 100% clean at minimum, but we're relatively confident that the current state of resolve makes it backwards compatible to add traits to the prelude.

Member

alexcrichton commented Jul 13, 2016

🔔 This issue is now entering a cycle-long final comment period for stabilization 🔔

As a point of stabilization, the libs team would also like to add these traits to the prelude as part of their stabilization. This will require a crater run being 100% clean at minimum, but we're relatively confident that the current state of resolve makes it backwards compatible to add traits to the prelude.

@ollie27

This comment has been minimized.

Show comment
Hide comment
@ollie27

ollie27 Jul 14, 2016

Contributor

I have a few questions about the purpose of these traits.

  1. Which types in std will these be implemented for?
  2. Which types should get implementations like impl TryFrom<T> for T?
  3. Which types should get implementations like impl TryFrom<U> for T if they already have impl From<U> for T?
Contributor

ollie27 commented Jul 14, 2016

I have a few questions about the purpose of these traits.

  1. Which types in std will these be implemented for?
  2. Which types should get implementations like impl TryFrom<T> for T?
  3. Which types should get implementations like impl TryFrom<U> for T if they already have impl From<U> for T?
@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Jul 14, 2016

Member

cc @sfackler, could you expand on the current set of impls and some of the rationale as well?

Member

alexcrichton commented Jul 14, 2016

cc @sfackler, could you expand on the current set of impls and some of the rationale as well?

@sfackler

This comment has been minimized.

Show comment
Hide comment
@sfackler

sfackler Jul 15, 2016

Member

I think in general the intuition should be exactly the same for that of From/Into, except when the conversion can fail. Just like we gradually add implementations of From and Into to standard library types, I expect we'll do the same for TryFrom and TryInto. The most important guideline here is that the conversion should be the "canonically obvious" one - if there's more than one reasonable way to convert one type to another, TryFrom or From may not be the right things to use.

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T. In particular, it's often not clear which error type to pick. However, those kinds of implementations are very much ones that can and should be defined to make a particular API work. For example, we have both of these kinds of implementations for various combinations of primitive integer types for the reasons outlined in the RFC. As another example, one ad-hoc trait that TryFrom/TryInto will replace is postgres::IntoConnectParams, which has a reflexive implementation to convert a ConnectParams into itself.

Member

sfackler commented Jul 15, 2016

I think in general the intuition should be exactly the same for that of From/Into, except when the conversion can fail. Just like we gradually add implementations of From and Into to standard library types, I expect we'll do the same for TryFrom and TryInto. The most important guideline here is that the conversion should be the "canonically obvious" one - if there's more than one reasonable way to convert one type to another, TryFrom or From may not be the right things to use.

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T. In particular, it's often not clear which error type to pick. However, those kinds of implementations are very much ones that can and should be defined to make a particular API work. For example, we have both of these kinds of implementations for various combinations of primitive integer types for the reasons outlined in the RFC. As another example, one ad-hoc trait that TryFrom/TryInto will replace is postgres::IntoConnectParams, which has a reflexive implementation to convert a ConnectParams into itself.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jul 15, 2016

Contributor

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T.

When a TryFrom conversion happens to be infallible the error type should be enum Void {}, right? (Or a similar enum with some other name.) Which by the way sounds to me like a good reason to have a general purpose Void type in std.

Contributor

SimonSapin commented Jul 15, 2016

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T.

When a TryFrom conversion happens to be infallible the error type should be enum Void {}, right? (Or a similar enum with some other name.) Which by the way sounds to me like a good reason to have a general purpose Void type in std.

@sfackler

This comment has been minimized.

Show comment
Hide comment
@sfackler

sfackler Jul 15, 2016

Member

@SimonSapin that would break an IntoConnectParams style API as well as the integer conversion use case outlined in the RFC since the error types of the infallible and fallible conversions wouldn't match.

Member

sfackler commented Jul 15, 2016

@SimonSapin that would break an IntoConnectParams style API as well as the integer conversion use case outlined in the RFC since the error types of the infallible and fallible conversions wouldn't match.

@glaebhoerl

This comment has been minimized.

Show comment
Hide comment
Contributor

glaebhoerl commented Jul 15, 2016

@Ericson2314

This comment has been minimized.

Show comment
Hide comment
@Ericson2314

Ericson2314 Jul 15, 2016

Contributor

@sfackler Not if you use plain From for the error types(e.g. try!)! impl<T> From<!> for T can and should exist for that purpose.

Contributor

Ericson2314 commented Jul 15, 2016

@sfackler Not if you use plain From for the error types(e.g. try!)! impl<T> From<!> for T can and should exist for that purpose.

@ollie27

This comment has been minimized.

Show comment
Hide comment
@ollie27

ollie27 Jul 16, 2016

Contributor

Just like we gradually add implementations of From and Into to standard library types, I expect we'll do the same for TryFrom and TryInto.

That doesn't appear to have happened yet so I don't know if it's because nobody has got round to it or there are no applicable types in std. If there are applicable types in std it would be nice to see some implementations for them. For example are any of the following good implementations?

impl TryFrom<u32> for char
impl TryFrom<char> for u8
impl TryFrom<Vec<u8>> for String
impl TryFrom<&[u8]> for &str

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T.

The issue is that if you want to use TryInto<T> and T isn't in your crate then you have to just hope that impl TryFrom<T> for T has been implemented. That's an unfortunate limitation, one which doesn't exist for From/Into.

@SimonSapin that would break an IntoConnectParams style API as well as the integer conversion use case outlined in the RFC since the error types of the infallible and fallible conversions wouldn't match.

Does this mean the error type is somehow fixed based on the type you're converting to?

Contributor

ollie27 commented Jul 16, 2016

Just like we gradually add implementations of From and Into to standard library types, I expect we'll do the same for TryFrom and TryInto.

That doesn't appear to have happened yet so I don't know if it's because nobody has got round to it or there are no applicable types in std. If there are applicable types in std it would be nice to see some implementations for them. For example are any of the following good implementations?

impl TryFrom<u32> for char
impl TryFrom<char> for u8
impl TryFrom<Vec<u8>> for String
impl TryFrom<&[u8]> for &str

In general, I don't think it should be expected that all types should impl TryFrom<T> for T or manually lift an impl From<U> for T.

The issue is that if you want to use TryInto<T> and T isn't in your crate then you have to just hope that impl TryFrom<T> for T has been implemented. That's an unfortunate limitation, one which doesn't exist for From/Into.

@SimonSapin that would break an IntoConnectParams style API as well as the integer conversion use case outlined in the RFC since the error types of the infallible and fallible conversions wouldn't match.

Does this mean the error type is somehow fixed based on the type you're converting to?

@malbarbo

This comment has been minimized.

Show comment
Hide comment
@malbarbo

malbarbo Jul 27, 2016

Contributor

Why TryFrom::Err and TryInto::Err is not bounded by std::error::Error?

Contributor

malbarbo commented Jul 27, 2016

Why TryFrom::Err and TryInto::Err is not bounded by std::error::Error?

@shepmaster

This comment has been minimized.

Show comment
Hide comment
@shepmaster

shepmaster Jul 27, 2016

Member

not bounded by std::error::Error?

That would prevent Err being (), which is a viable error type for infallible conversions.

Member

shepmaster commented Jul 27, 2016

not bounded by std::error::Error?

That would prevent Err being (), which is a viable error type for infallible conversions.

@Daggerbot

This comment has been minimized.

Show comment
Hide comment
@Daggerbot

Daggerbot Jul 31, 2016

If () is the error type, the function could return Err(()). This doesn't make the function infallible. It just fails to provide a useful error when it does fail. When writing code that uses conversions which may or may not be fallible, I think the best way is to bound by Into and write a specialization that uses TryInto.

If () is the error type, the function could return Err(()). This doesn't make the function infallible. It just fails to provide a useful error when it does fail. When writing code that uses conversions which may or may not be fallible, I think the best way is to bound by Into and write a specialization that uses TryInto.

@chris-morgan

This comment has been minimized.

Show comment
Hide comment
@chris-morgan

chris-morgan Aug 1, 2016

Member

Once RFC 1216 is implemented, ! will be the appropriate error type for infallible conversions. I think that would mean that an Error bound on TryFrom::Err/TryInto::Err would be OK.

I’d certainly like it if implementing From<T> yielded a TryFrom<T, Err = !> implementation (and ditto for Into, of course).

Member

chris-morgan commented Aug 1, 2016

Once RFC 1216 is implemented, ! will be the appropriate error type for infallible conversions. I think that would mean that an Error bound on TryFrom::Err/TryInto::Err would be OK.

I’d certainly like it if implementing From<T> yielded a TryFrom<T, Err = !> implementation (and ditto for Into, of course).

@canndrew

This comment has been minimized.

Show comment
Hide comment
@canndrew

canndrew Aug 1, 2016

Contributor

I think that would mean that an Error bound on TryFrom::Err/TryInto::Err would be OK.

Yes, we'll definitely have impl Error for ! { ... } for precisely these sorts of cases.

Contributor

canndrew commented Aug 1, 2016

I think that would mean that an Error bound on TryFrom::Err/TryInto::Err would be OK.

Yes, we'll definitely have impl Error for ! { ... } for precisely these sorts of cases.

@sfackler

This comment has been minimized.

Show comment
Hide comment
@sfackler

sfackler Aug 1, 2016

Member

I'm a bit worried about the type differences in the integer conversions use case, but it does seem like we should probably punt on stabilizing this until !-as-a-type lands to have a chance to experiment.

Member

sfackler commented Aug 1, 2016

I'm a bit worried about the type differences in the integer conversions use case, but it does seem like we should probably punt on stabilizing this until !-as-a-type lands to have a chance to experiment.

@malbarbo

This comment has been minimized.

Show comment
Hide comment
@malbarbo

malbarbo Aug 5, 2016

Contributor

In my POV all associated types that represents errors should be bounded by Error. Sadly, we already left one type without it: FromStr::Err (The only other public types are TryInto and TryFrom, checked with ack 'type Err;' and ack 'type Error;'). Let not make this again.

Contributor

malbarbo commented Aug 5, 2016

In my POV all associated types that represents errors should be bounded by Error. Sadly, we already left one type without it: FromStr::Err (The only other public types are TryInto and TryFrom, checked with ack 'type Err;' and ack 'type Error;'). Let not make this again.

@alexcrichton

This comment has been minimized.

Show comment
Hide comment
@alexcrichton

alexcrichton Aug 11, 2016

Member

Discussed recently, the libs team decided to punt on stabilizing these traits until the ! type is worked out.

Member

alexcrichton commented Aug 11, 2016

Discussed recently, the libs team decided to punt on stabilizing these traits until the ! type is worked out.

@Razican

This comment has been minimized.

Show comment
Hide comment
@Razican

Razican Aug 25, 2016

Contributor

I guess that now this is no longer blocked, right?

Contributor

Razican commented Aug 25, 2016

I guess that now this is no longer blocked, right?

@aturon aturon added the I-nominated label Aug 29, 2016

SimonSapin added a commit to SimonSapin/rust that referenced this issue Mar 26, 2018

SimonSapin added a commit to SimonSapin/rust that referenced this issue Mar 26, 2018

bors added a commit that referenced this issue Mar 27, 2018

Auto merge of #49305 - SimonSapin:fallible, r=<try>
Stabilize TryFrom / TryInto, and tweak impls for integers

Tracking issue: #33417

----

This adds:

* `impl From<u16> for usize`
* `impl From<i16> for isize`
* `impl From<u8> for isize`

… replacing corresponding `TryFrom<Error=!>` impls. (`TryFrom` still applies through the generic `impl<T, U> TryFrom<U> for T where T: From<U>`.) Their infallibility is supported by the C99 standard which (indirectly) requires pointers to be at least 16 bits.

The remaining `TryFrom` impls that define `type Error = !` all involve `usize` or `isize`. This PR changes them to use `TryFromIntError` instead, since having a return type change based on the target is a portability hazard.

Note: if we make similar assumptions about the *maximum* bit size of pointers (for all targets Rust will ever run on in the future), we could have similar `From` impls converting pointer-sized integers to large fixed-size integers. RISC-V considers the possibility of a 128-bit address space (RV128), which would leave only `impl From<usize> for u128` and `impl From<isize> for u128`. I [found](https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf) some [things](http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf) about 256-bit “capabilities”, but I don’t know how relevant that would be to Rust’s `usize` and `isize` types.

I chose conservatively to make no assumption about the future there. Users making their portability decisions and using something like `.try_into().unwrap()`.

----

Since this feature already went through FCP in the tracking issue #33417, this PR also proposes **stabilize** the following items:

* The `convert::TryFrom` trait
* The `convert::TryFrom` trait
* `impl<T> TryFrom<&[T]> for &[T; $N]` (for `$N` up to 32)
* `impl<T> TryFrom<&mut [T]> for &mut [T; $N]` (for `$N` up to 32)
* The `array::TryFromSliceError` struct, with impls of `Debug`, `Copy`, `Clone`, and `Error`
* `impl TryFrom<u32> for char`
* The `char::CharTryFromError` struct, with impls of `Copy`, `Clone`, `Debug`, `PartialEq`, `Eq`, `Display`, and `Error`
* Impls of `TryFrom` for all (?) combinations of primitive integer types where `From` isn’t implemented.
* The `num::TryFromIntError` struct, with impls of `Debug`, `Copy`, `Clone`, `Display`, `From<!>`, and `Error`

Some minor remaining questions that I hope can be resolved in this PR:

* Should the impls for error types be unified?
* ~Should `TryFrom` and `TryInto` be in the prelude? `From` and `Into` are.~ (Yes.)

bors added a commit that referenced this issue Mar 27, 2018

Auto merge of #49305 - SimonSapin:fallible, r=sfackler
Stabilize TryFrom / TryInto, and tweak impls for integers

Fixes #33417 (tracking issue)

----

This adds:

* `impl From<u16> for usize`
* `impl From<i16> for isize`
* `impl From<u8> for isize`

… replacing corresponding `TryFrom<Error=!>` impls. (`TryFrom` still applies through the generic `impl<T, U> TryFrom<U> for T where T: From<U>`.) Their infallibility is supported by the C99 standard which (indirectly) requires pointers to be at least 16 bits.

The remaining `TryFrom` impls that define `type Error = !` all involve `usize` or `isize`. This PR changes them to use `TryFromIntError` instead, since having a return type change based on the target is a portability hazard.

Note: if we make similar assumptions about the *maximum* bit size of pointers (for all targets Rust will ever run on in the future), we could have similar `From` impls converting pointer-sized integers to large fixed-size integers. RISC-V considers the possibility of a 128-bit address space (RV128), which would leave only `impl From<usize> for u128` and `impl From<isize> for u128`. I [found](https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf) some [things](http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf) about 256-bit “capabilities”, but I don’t know how relevant that would be to Rust’s `usize` and `isize` types.

I chose conservatively to make no assumption about the future there. Users making their portability decisions and using something like `.try_into().unwrap()`.

----

Since this feature already went through FCP in the tracking issue #33417, this PR also proposes **stabilize** the following items:

* The `convert::TryFrom` trait
* The `convert::TryFrom` trait
* `impl<T> TryFrom<&[T]> for &[T; $N]` (for `$N` up to 32)
* `impl<T> TryFrom<&mut [T]> for &mut [T; $N]` (for `$N` up to 32)
* The `array::TryFromSliceError` struct, with impls of `Debug`, `Copy`, `Clone`, and `Error`
* `impl TryFrom<u32> for char`
* The `char::CharTryFromError` struct, with impls of `Copy`, `Clone`, `Debug`, `PartialEq`, `Eq`, `Display`, and `Error`
* Impls of `TryFrom` for all (?) combinations of primitive integer types where `From` isn’t implemented.
* The `num::TryFromIntError` struct, with impls of `Debug`, `Copy`, `Clone`, `Display`, `From<!>`, and `Error`

Some minor remaining questions that I hope can be resolved in this PR:

* Should the impls for error types be unified?
* ~Should `TryFrom` and `TryInto` be in the prelude? `From` and `Into` are.~ (Yes.)
@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Mar 27, 2018

Contributor

Stabilization PR: #49305. After some discussion there, this PR also removes some TryFrom impls that involve usize or isize because we haven’t decided between two different ways to implement them. (And we can of course only have one.)

Dedicated tracking issue for those: #49415

Contributor

SimonSapin commented Mar 27, 2018

Stabilization PR: #49305. After some discussion there, this PR also removes some TryFrom impls that involve usize or isize because we haven’t decided between two different ways to implement them. (And we can of course only have one.)

Dedicated tracking issue for those: #49415

@kjetilkjeka

This comment has been minimized.

Show comment
Hide comment
@kjetilkjeka

kjetilkjeka Apr 29, 2018

TryFrom worked perfectly on rustc 1.27.0-nightly (ac3c2288f 2018-04-18) without any feature gating but broke when compiled with rustc 1.27.0-nightly (66363b288 2018-04-28).

Have there been any regressions to stabilization of this feature the last 10 days?

TryFrom worked perfectly on rustc 1.27.0-nightly (ac3c2288f 2018-04-18) without any feature gating but broke when compiled with rustc 1.27.0-nightly (66363b288 2018-04-28).

Have there been any regressions to stabilization of this feature the last 10 days?

@kennytm

This comment has been minimized.

Show comment
Hide comment
@kennytm

kennytm Apr 29, 2018

Member

@kjetilkjeka This feature has been recently unstabilized: #50121.

(Reopening since stabilization has been reverted)

Member

kennytm commented Apr 29, 2018

@kjetilkjeka This feature has been recently unstabilized: #50121.

(Reopening since stabilization has been reverted)

@kennytm kennytm reopened this Apr 29, 2018

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Apr 29, 2018

Contributor

@kjetilkjeka The stabilization of TryFrom has been reverted in #50121 together with the stabilization of the ! type, because of the TryFrom<U, Error=!> for T where T: From<U> impl. The ! type was unstabilized because of #49593.

Contributor

SimonSapin commented Apr 29, 2018

@kjetilkjeka The stabilization of TryFrom has been reverted in #50121 together with the stabilization of the ! type, because of the TryFrom<U, Error=!> for T where T: From<U> impl. The ! type was unstabilized because of #49593.

@kjetilkjeka

This comment has been minimized.

Show comment
Hide comment
@kjetilkjeka

kjetilkjeka Apr 29, 2018

Thanks for explaining. Does this mean that this feature is essentially blocked on some changes to the compiler type coercion? I can't find an issue explaining what changes are required, is the magnitude of changes known at this point?

Thanks for explaining. Does this mean that this feature is essentially blocked on some changes to the compiler type coercion? I can't find an issue explaining what changes are required, is the magnitude of changes known at this point?

@joshtriplett

This comment has been minimized.

Show comment
Hide comment
@joshtriplett

joshtriplett May 21, 2018

Member

Is there some fundamental reason that we couldn't go ahead and stabilize the TryFrom trait itself, and any impls that do not involve !, and just defer stabilizing impls involving ! until after the possible stabilization of !?

#49305 (comment) classifies the various possible trait implementations.

Member

joshtriplett commented May 21, 2018

Is there some fundamental reason that we couldn't go ahead and stabilize the TryFrom trait itself, and any impls that do not involve !, and just defer stabilizing impls involving ! until after the possible stabilization of !?

#49305 (comment) classifies the various possible trait implementations.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 22, 2018

Contributor

@joshtriplett As far as I understand, impl<T, U> TryFrom<T> for U where U: From<T> { type Err = !; } in particular is not backward-compatible to add if TryFrom has already been stable.

Contributor

SimonSapin commented May 22, 2018

@joshtriplett As far as I understand, impl<T, U> TryFrom<T> for U where U: From<T> { type Err = !; } in particular is not backward-compatible to add if TryFrom has already been stable.

@joshtriplett

This comment has been minimized.

Show comment
Hide comment
@joshtriplett

joshtriplett May 22, 2018

Member

@SimonSapin
Why is that not backward-compatible to add?

(And do we really need the blanket impl?)

Member

joshtriplett commented May 22, 2018

@SimonSapin
Why is that not backward-compatible to add?

(And do we really need the blanket impl?)

@kjetilkjeka

This comment has been minimized.

Show comment
Hide comment
@kjetilkjeka

kjetilkjeka May 22, 2018

Why is that not backward-compatible to add?

I think it's not backward compatible since TryFrom could have been implemented manually between TryFrom was stabilized and ! was stabilized. When the blanket implementation was added it would be conflicting with the manual implementation.

(And do we really need the blanket impl?)

I think the blanket impl really makes sense when writing generic code over TryFrom. When referring to all types that have a possibility for conversion into T you would most of the time also want to include all types that can be converted into T for sure. I assume an alternative could be to require everyone to also implement TryFrom for all types that implement From and wait for specialization before making the blanket impl. You would still have the problem of what Err to make Result generic over. ! seems like a nice way to both express and programatically enforce the infallibility of the conversion, and hopefully worth the wait.

kjetilkjeka commented May 22, 2018

Why is that not backward-compatible to add?

I think it's not backward compatible since TryFrom could have been implemented manually between TryFrom was stabilized and ! was stabilized. When the blanket implementation was added it would be conflicting with the manual implementation.

(And do we really need the blanket impl?)

I think the blanket impl really makes sense when writing generic code over TryFrom. When referring to all types that have a possibility for conversion into T you would most of the time also want to include all types that can be converted into T for sure. I assume an alternative could be to require everyone to also implement TryFrom for all types that implement From and wait for specialization before making the blanket impl. You would still have the problem of what Err to make Result generic over. ! seems like a nice way to both express and programatically enforce the infallibility of the conversion, and hopefully worth the wait.

@joshtriplett

This comment has been minimized.

Show comment
Hide comment
@joshtriplett

joshtriplett May 22, 2018

Member

We could always wait until specialization is available to provide the blanket impl, and stabilize the various numeric conversions in the interim.

I've seen various requests for these in the context of people seeking help for how to do integer conversions idiomatically in Rust, and just today ran into someone who specifically wondered how they should convert u64 to u32 with error detection.

Member

joshtriplett commented May 22, 2018

We could always wait until specialization is available to provide the blanket impl, and stabilize the various numeric conversions in the interim.

I've seen various requests for these in the context of people seeking help for how to do integer conversions idiomatically in Rust, and just today ran into someone who specifically wondered how they should convert u64 to u32 with error detection.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin May 22, 2018

Contributor

I’m not convinced that specialization will magically allow adding the blanket impl after the fact. My understanding of current proposals is that a trait must opt into being specializable, which may not be backward-compatible to do on existing traits.

Contributor

SimonSapin commented May 22, 2018

I’m not convinced that specialization will magically allow adding the blanket impl after the fact. My understanding of current proposals is that a trait must opt into being specializable, which may not be backward-compatible to do on existing traits.

@SergioBenitez

This comment has been minimized.

Show comment
Hide comment
@SergioBenitez

SergioBenitez Jun 7, 2018

Contributor

For whenever this is stabilized: please add TryFrom and TryInto to the prelude.

Contributor

SergioBenitez commented Jun 7, 2018

For whenever this is stabilized: please add TryFrom and TryInto to the prelude.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jun 7, 2018

Contributor

@SergioBenitez We’ve done that on Nightly for a while, and unfortunately it was a breaking change for crates that define their own TryFrom or TryInto trait (for use while the std ones are unstable), enough that we’ve reverted it.

I think the lesson to learn here for the std libs team is that when there’s a trait that we might want to add to the prelude, we should do so as soon as it’s implemented and not wait for stabilization.

For TryFrom and TryInto however, a solution would be to have a different prelude for the 2018 edition. This has been discussed informally before but I didn’t find it filed, so I opened #51418.

Contributor

SimonSapin commented Jun 7, 2018

@SergioBenitez We’ve done that on Nightly for a while, and unfortunately it was a breaking change for crates that define their own TryFrom or TryInto trait (for use while the std ones are unstable), enough that we’ve reverted it.

I think the lesson to learn here for the std libs team is that when there’s a trait that we might want to add to the prelude, we should do so as soon as it’s implemented and not wait for stabilization.

For TryFrom and TryInto however, a solution would be to have a different prelude for the 2018 edition. This has been discussed informally before but I didn’t find it filed, so I opened #51418.

@stuhood

This comment has been minimized.

Show comment
Hide comment
@stuhood

stuhood Jun 8, 2018

stuhood commented Jun 8, 2018

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jun 8, 2018

Contributor

In this case what’s colliding is not the traits themselves (the name of the item in the prelude) but the methods brought into scope by that trait. Maybe there’s still some similar tweak we can do, but it’s more subtle.

Contributor

SimonSapin commented Jun 8, 2018

In this case what’s colliding is not the traits themselves (the name of the item in the prelude) but the methods brought into scope by that trait. Maybe there’s still some similar tweak we can do, but it’s more subtle.

@nayato

This comment has been minimized.

Show comment
Hide comment
@nayato

nayato Jun 15, 2018

@SimonSapin what's the current plan for TryFrom/TryInto stabilization? I couldn't find anything concrete beyond it being reverted on Apr 29.

nayato commented Jun 15, 2018

@SimonSapin what's the current plan for TryFrom/TryInto stabilization? I couldn't find anything concrete beyond it being reverted on Apr 29.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jun 15, 2018

Contributor

@nayato It is blocked on stabilizing (again) the never type #35121, which itself is blocked on #49593.

Contributor

SimonSapin commented Jun 15, 2018

@nayato It is blocked on stabilizing (again) the never type #35121, which itself is blocked on #49593.

@npmccallum

This comment has been minimized.

Show comment
Hide comment
@npmccallum

npmccallum Jul 14, 2018

Contributor

@SimonSapin The never type is only used here. Could we stabilize TryFrom without that implementation and land it when never is stabilized? TryFrom is a pretty important interface even apart from the equivalence with Try.

Contributor

npmccallum commented Jul 14, 2018

@SimonSapin The never type is only used here. Could we stabilize TryFrom without that implementation and land it when never is stabilized? TryFrom is a pretty important interface even apart from the equivalence with Try.

@SimonSapin

This comment has been minimized.

Show comment
Hide comment
@SimonSapin

SimonSapin Jul 14, 2018

Contributor

Unfortunately not. It would be a breaking change to add this blanket impl after the trait has been stabilized and crates.io libraries have had a chance to implement for example TryFrom<Foo> for Bar while they also have From<Foo> for Bar, as the impls would overlap.

The decision so far has been that making TryFrom "compatible" in this way with From was important enough to block stabilization.

Contributor

SimonSapin commented Jul 14, 2018

Unfortunately not. It would be a breaking change to add this blanket impl after the trait has been stabilized and crates.io libraries have had a chance to implement for example TryFrom<Foo> for Bar while they also have From<Foo> for Bar, as the impls would overlap.

The decision so far has been that making TryFrom "compatible" in this way with From was important enough to block stabilization.

@regexident

This comment has been minimized.

Show comment
Hide comment
@regexident

regexident Jul 14, 2018

Contributor

Probably naïve and silly thought:

What if rustc got an always-on error lint in the meanwhile that triggered for Error<_, !>, preventing any impls in userland, allowing for addition of impls later on?

Contributor

regexident commented Jul 14, 2018

Probably naïve and silly thought:

What if rustc got an always-on error lint in the meanwhile that triggered for Error<_, !>, preventing any impls in userland, allowing for addition of impls later on?

@jethrogb

This comment has been minimized.

Show comment
Hide comment
@jethrogb

jethrogb Jul 14, 2018

Contributor

Or an unstable impl<T: From<U>, U> TryFrom<U> for T with any error type. Can trait impls be unstable?

Contributor

jethrogb commented Jul 14, 2018

Or an unstable impl<T: From<U>, U> TryFrom<U> for T with any error type. Can trait impls be unstable?

@sfackler

This comment has been minimized.

Show comment
Hide comment
Member

sfackler commented Jul 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment