# Standardize on From/Into for all conversions

**URL:** <https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554>\
**Category:** Uncategorized\
**Created:** [October 13, 2018, 2:57pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554 "2018-10-13T14:57:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [October 13, 2018, 2:57pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/1 "2018-10-13T14:57:38Z")

</div>

All conversions, especially those of TryFrom and Try, should use From/Into. E.g.

```rust
pub trait MyTry where Self: Into<Result<<Self as MyTry>::Ok, <Self as MyTry>::Error>>, <Self as MyTry>::Ok: Into<Self> {
    type Ok;
    type Error;
    fn from_error(e: <Self as MyTry>::Error) -> Self;
}

impl<T, E> MyTry for Result<T, E> where E: Into<Self>, T: Into<Self> {
    type Ok = T;
    type Error = E;
    fn from_error(e: E) -> Self {
        Err(e)
    }
}

#[derive(Eq, PartialEq)]
struct Foo;

// this should be impl<T> From<T> for Result<T, E>
impl<E> Into<Result<Foo, E>> for Foo {
    fn into(self) -> Result<Foo, E> {
        Ok(self)
    }
}

fn main() {
    let o: Result<Foo, Foo> = Foo.into();
    let e: Result<Foo, Foo> = MyTry::from_error(Foo);
    assert!(o != e);
}

```

(note that `from_error` is, sadly, still necessary. but also note that we don’t need into\_result or from\_ok, as those can be done with From/Into! this provides a more generic stdlib, so using it is easier! also note that we automatically get a TryFrom - From for Result\<T, E\> is equivalent to but better than TryFrom for T!)

---

<div class="post-metadata">

**Author:** ![storyfeet](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/storyfeet/32/4461_2.png) [@storyfeet](https://internals.rust-lang.org/u/storyfeet)\
**Post date:** [October 13, 2018, 3:04pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/2 "2018-10-13T15:04:40Z")

</div>

But TryFrom can fail, and From can’t.

They are fundamentally different operations.

If I have a guaranteed operation. I don’t want to handle errors. and if I have an error case I need to.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [October 13, 2018, 3:05pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/3 "2018-10-13T15:05:47Z")

</div>

`From<U> for Result<T, E>` can fail.

e.g.

```rust
impl From<u16> for Result<u8, !> {
    fn From(v: u16) -> Self {
        if v > 255 { panic!(); }
        Ok(mem::transmute::<[u8;2]>(v)[0])
    }
}

```

I use From/Into all the time, let me use it more.

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [October 13, 2018, 3:23pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/4 "2018-10-13T15:23:09Z")

</div>

Small note: I think the title of this thread sounds a bit misleading; it sounds like you’re saying we should get rid of `TryInto` and just use `Into<T>`; but after reading it I think I see you are suggesting that trait methods like `Try::from_ok` and `Try::into_result` should not exist and ought to be provided through `Into`.

Suggestion: change “all conversions” to “all conversions in traits?”

* * *

I’m against this for the same reasoning I was against [using `Into<Option<T>>` for an operator in another thread](https://internals.rust-lang.org/t/pre-rfc-elvis-coalesce-ternary-operator/8537/21?u=exphp).

Using one trait (`Into`) for a large multitude of purposes makes the language less powerful. We will run into cases where we are forced to choose between one feature or another for our type because the `Into` impls we want to write would overlap.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [October 13, 2018, 3:28pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/5 "2018-10-13T15:28:34Z")

</div>

I believe the general-ness of Into actually makes the language _more_ powerful, even if it could restrict what impls you may use. I use the term “could” here, because I believe newtypes solve that problem.

In the general case, these impls would provide great ergonomics/convenience for most operations. In the few edge cases where they don’t, you’d be able to use newtypes and it would no longer be a big deal.

“Make simple things simple and complex things possible” - someone

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [October 13, 2018, 3:43pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/6 "2018-10-13T15:43:12Z")

</div>

> [@Soni](#):
>
> In the general case, these impls would provide great ergonomics/convenience for most operations. In the few edge cases where they don’t, you’d be able to use newtypes and it would no longer be a big deal.

My gut reaction is that needing to wrap something in a newtype to use some functionality can be unergonomic for consumers of a type---especially if these values may be inside a container. (e.g. changing `Vec<T>` to `Vec<MyNewtype<T>>` requires allocation, and changing `&[T]` to `&[MyNewtype<T>]` requires `unsafe`)

Clearly, we disagree on how big of a problem overlap will be in practice. You don't believe it will happen often, whereas I fear it will happen all over the place. (As I see it, overlap happens quite often enough even when we _aren't_ overloading the meaning of traits!).

The only way to know for sure is to try implementing it at a large scale.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [October 13, 2018, 5:08pm UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/7 "2018-10-13T17:08:44Z")

</div>

> [@ExpHP](#):
>
> My gut reaction is that needing to wrap something in a newtype to use some functionality can be unergonomic for consumers of a type—especially if these values may be inside a container. (e.g. changing `Vec<T>` to `Vec<MyNewtype<T>>` requires allocation, and changing `&[T]` to `&[MyNewtype<T>]` requires `unsafe` )

See [Looking for RFC coauthors on "named impls"](https://internals.rust-lang.org/t/looking-for-rfc-coauthors-on-named-impls/6275)

> [@ExpHP](#):
>
> Clearly, we disagree on how big of a problem overlap will be in practice. You don’t believe it will happen often, whereas I fear it will happen all over the place. (As I see it, overlap happens quite often enough even when we _aren’t_ overloading the meaning of traits!).
> 
> The only way to know for sure is to try implementing it at a large scale.

I would like the nightly compiler to have "A/B testing" mode. But I don't think that's implemented yet.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:16am UTC](https://internals.rust-lang.org/t/standardize-on-from-into-for-all-conversions/8554/8 "2019-03-25T08:16:52Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
