Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd TryFrom and TryInto traits #1542
Conversation
sfackler
self-assigned this
Mar 12, 2016
This comment has been minimized.
This comment has been minimized.
|
Additional existing third party trait: hyper::IntoUrl. |
This comment has been minimized.
This comment has been minimized.
comex
commented
Mar 13, 2016
|
|
This comment has been minimized.
This comment has been minimized.
|
I wonder how this interacts with enum casting? Will it be possible to cast an integral representation to an enum variant? |
This comment has been minimized.
This comment has been minimized.
|
@comex one of the major motivations for implementing fallible conversion traits for integers is for FFI use cases. Could you clarify how you see ergonomic casts between, for example, |
petrochenkov
reviewed
Mar 13, 2016
|
|
||
| ```rust | ||
| let value: isize = ...; | ||
| let value: u32 = try!(value.try_into()); |
This comment has been minimized.
This comment has been minimized.
petrochenkov
Mar 13, 2016
Contributor
This example is pretty untypical.
These overflows, like arithmetic overflows, are very rarely handled, so most of the time people will have to deal with
let value: u32 = value.try_into().unwrap();
This comment has been minimized.
This comment has been minimized.
sfackler
Mar 13, 2016
Author
Member
It's not all that uncommon in my experience:
https://github.com/sfackler/rust-postgres/blob/master/src/types/mod.rs#L700
https://github.com/sfackler/rust-postgres-large-object/blob/master/src/lib.rs#L220
But in any case, what you do with the Err once you get it doesn't really have much to do with this RFC - it's focused on how you get that Err.
petrochenkov
reviewed
Mar 13, 2016
| Are `TryFrom` and `TryInto` the right names? There is some precedent for the | ||
| `try_` prefix: `TcpStream::try_clone`, `Mutex::try_lock`, etc. | ||
|
|
||
| What should be done about `FromStr`, `ToSocketAddrs`, and other ad-hoc fallible |
This comment has been minimized.
This comment has been minimized.
petrochenkov
Mar 13, 2016
Contributor
I dislike the tendency of replacing concrete methods with meaningless generic implementations.
I'd never want parse(&str) -> Result<i32, Err> to become try_into(&str) -> Result<i32, Err>.
From/Into are already overused in this sense, impl From<Ipv4Addr> for u32 goddamit.
Is anyone going to write generic code which would be applicable to both FromStr and ToSocketAddrs? I suppose no. It means than TryFrom/TryInto in this case is a dangerous over-generalization.
I'm not against TryFrom/TryInto in principle, but I'm pretty sure they will be heavily misused.
This comment has been minimized.
This comment has been minimized.
SimonSapin
Mar 13, 2016
Contributor
I don’t know what should be concluded from this, but note that ToSocketAddrs has an associated type for the Ok case.
This comment has been minimized.
This comment has been minimized.
sfackler
Mar 13, 2016
Author
Member
@petrochenkov Why do you feel that impl FromStr for Foo is an intrinsically more meaningful implementation than impl<'a str> TryFrom<&'a str> for Foo? They seem totally isomorphic to me.'
It's also worth noting that the fate of parse is basically unrelated to the fate of FromStr.
This comment has been minimized.
This comment has been minimized.
petrochenkov
Mar 14, 2016
Contributor
It's also worth noting that the fate of parse is basically unrelated to the fate of FromStr.
parse itself is not affected, it'll just get a generic duplicate try_into if TryFrom<str> is implemented for the same types as FromStr and TryInto gets the blanket impl based on TryFrom.
And I'm saying that this duplicate will almost never be used, because parse is preferable in concrete code and probably never used in code generic enough to not be able to use parse.
Why do you feel that impl FromStr for Foo is an intrinsically more meaningful implementation than impl<'a str> TryFrom<&'a str> for Foo?
I don't feel that way with respect to FromStr in particular, FromStr is already meaningless enough :)
nrc
added
the
A-libs
label
Mar 13, 2016
alexcrichton
added
T-libs
and removed
A-libs
labels
Mar 14, 2016
This comment has been minimized.
This comment has been minimized.
jimmycuadra
commented
Mar 16, 2016
|
From an API discoverability perspective, I think these traits would be useful. I was looking for something that did this a while back and was surprised to find that there was no fallible equivalent of |
This comment has been minimized.
This comment has been minimized.
Zoxc
commented
Mar 28, 2016
|
I would like the signature of the methods to be changed to return For example in this function: fn coerce<B, A: TryInto<B> + Debug>(from: A) -> B {
match from.try_into() {
Ok(v) => v,
Err((f, err)) => {
panic!("Cannot coerce value {} of type {} into type {} because {}", f, type_name::<A>(), type_name::<B>(), err);
}
}
}Alternatively there could be a method on the error giving a way to extract it. |
This comment has been minimized.
This comment has been minimized.
|
I think that's a good idea. A lot of |
This comment has been minimized.
This comment has been minimized.
|
To repeat my comment in rust-lang/rust#31405, the naming convention of The |
alexcrichton
added
the
final-comment-period
label
Apr 15, 2016
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
Overall I like the idea of having these traits in the standard library as they provide a nice vector for us to implement all sorts of conversions in a standardized fashion. I also think that the naming here, (as @SimonSapin mentioned) seems good (I'm personally less worried about the On question I'd have is whether we'd want to add these traits to the prelude? One of the reasons Finally, as to some other points brought up on this RFC:
|
nagisa
reviewed
Apr 18, 2016
|
|
||
| ```rust | ||
| impl<T, U> TryInto<U> for T where U: TryFrom<T> { | ||
| type Error = U::Err; |
This comment has been minimized.
This comment has been minimized.
nagisa
reviewed
Apr 18, 2016
| However, this implementation would directly conflict with our goal of having | ||
| uniform `TryFrom` implementations between all combinations of integer types. In | ||
| addition, it's not clear what value such an implementation would actually | ||
| provide, so this RFC does *not* propose its addition. |
This comment has been minimized.
This comment has been minimized.
nagisa
Apr 18, 2016
Contributor
I think this is a very important implementation to add.
I write code like this all the time:
fn foo<T: Into<Bar>>(bar: T) -> … {
let bar = bar.into();
}
which then can be used with anything that implements From. I would certainly like to be able to do
fn foo_2<T: TryInto<Bar>>(bar: T) -> … {
let bar = bar.try_into().unwrap();
}
and be able to pass in anything implementing plain old From as well.
The coherence problem could’ve been a reason for not considering this at the time of writing, but since specialisation has been implemented, perhaps it can be made to work?
This comment has been minimized.
This comment has been minimized.
sfackler
Apr 18, 2016
Author
Member
I do not believe this can be done in the current implementation of specialization.
This comment has been minimized.
This comment has been minimized.
aturon
Apr 19, 2016
Member
Yes, IIRC this requires the "lattice rule". (I expect something with that level of expressiveness to be available eventually, but it will be a while.)
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
It seems to me that there would be very few contexts in which you'd actually be able to implement |
This comment has been minimized.
This comment has been minimized.
nodakai
commented
Apr 19, 2016
|
On which types are we going to implement the proposed traits?
Also, the proposed interface does not obviously eliminate such silly implementations like fn try_from(t: usize) -> Result<u8, TryFromIntError> { Ok(42) }Is it possible to add kind of "axioms" that all implementers should satisfy? For example, for let x0: S = ...;
let x1: S = ...;
let y0: T = x0.try_into()?;
let y1: T = x1.try_into()?;
assert_eq!(x0 == x1, y0 == y1); |
This comment has been minimized.
This comment has been minimized.
|
I'm in favor of this RFC. To me, the biggest use-case is ergonomic overloaded construction via @alexcrichton has already made most of the other points I wanted to, so I'll leave it at |
This comment has been minimized.
This comment has been minimized.
The traits are for things that can be converted to another type in a potentially fallible way, and as is the case for Implementations of
In what way is this different from any other interface in the standard library? We can't guard against pathologically malicious implementors.
I do not see us making any strong guarantees in this sense - we don't for |
This comment has been minimized.
This comment has been minimized.
|
The prelude question is pretty complicated. We certainly can't add these traits to the prelude with the current resolve implementation. The I think these will be useful/used in practice for integral conversions because they are already a pain to write. Something like this: // ...
let x = if x < 0 || x > u32::max_value() as i64 {
return Err(Whatever);
} else {
x as u32
};will be simplified to use std::convert::TryInto;
// ...
let x = try!(x.try_into()); |
This comment has been minimized.
This comment has been minimized.
ollie27
commented
Apr 19, 2016
|
I'm also curious if there are any concrete use cases other than int to int conversions which in my opinion are much better handled by something like #1218?
I assume this was meant to say primitive integers as all primitive types doesn't make any sense. One of the main advantages of I kind of think fallible conversions can be left a bit ad hoc, for example |
This comment has been minimized.
This comment has been minimized.
|
@ollie27 The RFC mentions some in the motivation section. Here's a list of traits that all do this off the top of my head:
|
This comment has been minimized.
This comment has been minimized.
FWIW |
This comment has been minimized.
This comment has been minimized.
( |
This comment has been minimized.
This comment has been minimized.
Why exactly?
Prelude names are shadowable, if code uses |
This comment has been minimized.
This comment has been minimized.
|
Hmm, I may have imagined that there would be more troubles adding this to the prelude than there are. |
This comment has been minimized.
This comment has been minimized.
nodakai
commented
Apr 24, 2016
I thought it would be nice to discuss how far it should be expanded in the future at this stage, and in order to do so, we need some guideline on its applicability.
I might argue that's just an unfortunate lack and shouldn't be taken as the norm. The prominent applications of the proposed crates are built-in integers, and their success/failure will be defined by whether "the value is preserved" or not, right? I was wondering if all the implementers could follow an extended definition of "value-preserving."
As @SimonSapin pointed out, it can still make sense without DNS, but anyways, I'd argue this is exactly why I'd like to bring up the point at this stage, not at the implementation phase. |
alexcrichton
referenced this pull request
May 4, 2016
Open
Tracking issue for TryFrom/TryInto traits #33417
This comment has been minimized.
This comment has been minimized.
|
The libs team discussed this RFC at triage today and the decision was to merge. We had some small discussion about the prelude-ness of these traits, but the conclusion was that this likely wants to wait until they're stable in any case. Thanks again for the RFC @sfackler! Tracking issue: rust-lang/rust#33417 |
alexcrichton
merged commit adc2547
into
rust-lang:master
May 4, 2016
This comment has been minimized.
This comment has been minimized.
Kixunil
commented
Sep 21, 2016
•
|
@petrochenkov Regarding P.S. I hope I didn't do any harm by replying late and little bit off-topic. (Please let me know if I should avoid doing it in the future.) |
jimmycuadra
referenced this pull request
Aug 16, 2017
Open
Things blocking or slowing progress of Ruma #189
This was referenced Mar 30, 2018
This comment has been minimized.
This comment has been minimized.
Lonami
commented on text/0000-try-from.md in adc2547
Jun 1, 2018
|
Hm… that's a broken link now. We could either link to the source code on that version or the docs for 0.11.3 since the version 0.11.4 failed to build. Do we do this kind of fixes with already published RFCs? I was reading about |
This comment has been minimized.
This comment has been minimized.
Kroc
commented
Sep 17, 2018
•
|
Just learning Rust, and was surprised this wasn't in stable! I'm writing an assembler and I'm using a data-driven methodology where I'm avoiding any functions; all computing is done by type conversion; e.g. you want to parse a string? Convert it into a
|
This comment has been minimized.
This comment has been minimized.
|
We all are. It’s run into some really unfortunate issues. Until then, there’s the crates.io package.
… On Sep 17, 2018, at 6:36 AM, Kroc Camen ***@***.***> wrote:
Just learning Rust, and was surprised this wasn't in stable! I'm writing an assembler and I'm using a data-driven methodology where I'm avoiding any functions; all computing is done by type conversion; e.g. you want to parse a string? Convert it into a TokenStream, the logic is internal. Where this falls apart is fallibility; If I'm trying to convert a string token to a scalar value (such as parse), there isn't an easy way to error handle this other than panics.
TryFrom solves my issue perfectly!
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
sfackler commentedMar 12, 2016
Rendered