-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add TryFrom and TryInto traits #1542
Conversation
Additional existing third party trait: hyper::IntoUrl. |
👎 on implementing it for infallible conversions. |
I wonder how this interacts with enum casting? Will it be possible to cast an integral representation to an enum variant? |
@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, |
|
||
```rust | ||
let value: isize = ...; | ||
let value: u32 = try!(value.try_into()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
.
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 |
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. |
I think that's a good idea. A lot of |
To repeat my comment in rust-lang/rust#31405, the naming convention of The |
🔔 This RFC is now entering its week-long final comment period 🔔 |
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:
|
|
||
```rust | ||
impl<T, U> TryInto<U> for T where U: TryFrom<T> { | ||
type Error = U::Err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Err
, not Error
.
|
It seems to me that there would be very few contexts in which you'd actually be able to implement |
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); |
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 👍! |
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 |
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()); |
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 |
@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:
|
FWIW |
( |
Why exactly?
Prelude names are shadowable, if code uses |
Hmm, I may have imagined that there would be more troubles adding this to the prelude than there are. |
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. |
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 |
@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.) |
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
|
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.
|
Rendered