# Mini pre-RFC: Make \`Into\` trait object safe

**URL:** <https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827>\
**Category:** libs\
**Created:** [November 13, 2018, 4:12am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827 "2018-11-13T04:12:40Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 4:12am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/1 "2018-11-13T04:12:40Z")

</div>

# Summary

Change the definition of `Into` trait such that it does not require `Self: Sized`.

```rust
pub trait Into<T> {
    /// Performs the conversion.
    fn into(self) -> T;
}

```

# Motivation

As we don’t have `#[feature(unsized_locals)]` before, we don’t want to allow `dyn Into<T>` because it will be useless.

Once we allow object safe methods to receive `self` by value, the reason above disappears.

Enabling `dyn Into<T>` on the other hand, enables a lot of new abstractions to appear, and it can be seen as Rust’s standard representation of lazy evaluations. For example, we can image the short circuit boolean operation being defined as

```rust
trait And<Rhs=Self> {
    type Output;
    fn and(self, rhs: dyn Into<Rhs>) -> Self::Output;
}
impl And for bool {
    type Output = bool;
    fn and(self, rhs: dyn Into<bool>) -> bool {
        if self { return true } else { rhs.into() }
    }
}

```

(The above is not implied in this RFC, only demonstrates future improvement possibilities).

(However, many other traits in `std::ops` can be relaxed like this, I am not sure shall I included them as well.)

(`Add/Div/...` were already relaxed…)

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 4:50am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/2 "2018-11-13T04:50:02Z")

</div>

This would require [unsized rvalues](https://github.com/rust-lang/rust/issues/48055), which is currently in the works. There is no other way to make this change, because changing the signature of `Into` would be a breaking change. Currently this is impossible to do.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 4:51am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/3 "2018-11-13T04:51:10Z")

</div>

> [@RustyYato](#):
>
> This would require [unsized rvalues](https://github.com/rust-lang/rust/issues/48055),

Yes this is what I am going to say. But is this already in stabilizing?

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 4:56am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/4 "2018-11-13T04:56:27Z")

</div>

Yes, it has been accepted, but right now it isn’t implemented, so it may take a while to get it. Also just because a RFC gets accepted, doesn’t mean it will get stabilized (see [placement new](https://github.com/rust-lang/rust/issues/27779)). That said, I doubt unsized rvalues will be unaccepted.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 4:59am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/5 "2018-11-13T04:59:51Z")

</div>

I just noticed this was already implemented.

```rust
#![feature(unsized_locals)]
...
let v:Box<dyn FnOnce()> = Box::new(||{});
v()

```

is now working.

I also have issued a bug regarding miri.

> <https://github.com/rust-lang/rust/issues/55815>

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 5:02am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/6 "2018-11-13T05:02:11Z")

</div>

This is [coercions](https://github.com/rust-lang/rust/issues/27732) at work, not the same as unsized rvalues.

With unsized rvalues I could do

```rust
let f: dyn FnOnce() = || ();
f();

```

Which is currently illegal.

The related traits for coercion are [`std::ops::CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html) and [`std::marker::Unsize`](https://doc.rust-lang.org/std/marker/trait.Unsize.html)

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 5:04am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/7 "2018-11-13T05:04:22Z")

</div>

Ok. But as long as we know that `into` is callable when `dyn Into` do exist, it is still already possible to use `dyn Into` right? So I didn’t see a reason to stop this. Maybe the `And` example I gave is too early and require something else, but making `dyn Into` usable is already implemented.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 5:22am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/8 "2018-11-13T05:22:28Z")

</div>

I’m not trying to stop this (I probably could have communicated that better), I just want it noted that this pre-RFC will depend on something which is currently not even implemented (unsized rvalues). Also, currently it would not be possible to call `into` if we had a `dyn Into` because `Self` is `dyn Into`, which is `!Sized`. `!Sized` values cannot be used on the stack, because their size is unknown at compile time and because of this we cannot initialize the `self` parameter of `into`. Due to this, it is impossible to call `into` without unsized rvalues (which will allow `!Sized` values on the stack) or a change to `into`'s signature (which not an option due to stability concerns).

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 5:23am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/9 "2018-11-13T05:23:19Z")

</div>

> [@earthengine](#):
>
> `And` example

What do you mean by this? (I don't see any `And` example)

--edit--

I missed the example in the pre-RFC while trying to find it 😅

* * *

edit 2

> [@earthengine](#):
>
> ```rust
> impl And for bool {
> type Output = bool;
> fn and(self, rhs: dyn Into<bool>) -> bool {
> if self { return true } else { rhs.into() }
> }
> }
> 
> ```

It is already possible to implement this in another way

```rust
impl<Rhs: Into<bool>> And<Rhs> for bool {
    type Output = bool;
    fn and(self, rhs: Rhs) -> bool {
        if self { return true } else { rhs.into() }
    }
}

```

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 5:30am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/10 "2018-11-13T05:30:52Z")

</div>

In my top post I have a example that defines a `And` trait.

I can confirm though, if I simply define a new trait

[Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=c0d7404a4d7303e2cda38c1e76b09522)

```rust
trait NewInto<T> {
    fn new_into(self) -> T;
}
impl<T,I:Into<T>> NewInto<T> for I {
    fn new_into(self) -> T {
        self.into()
    }
}

fn main() {
    let b:Box<dyn NewInto<i32>> = Box::new(10);
    println!("{}", (*b).new_into())
}

```

It is just working.

> [@RustyYato](#):
>
> It is already possible to implement this in another way

Oh. Maybe I would need better example then.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 5:48am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/11 "2018-11-13T05:48:03Z")

</div>

> [@earthengine](#):
>
> It is just working.

Oh, ok. Then it is implemented, at part of it.

> [@earthengine](#):
>
> Oh. Maybe I would need better example then.

Yes

> [@earthengine](#):
>
> representation of lazy evaluations

As I showed before, this problem can be solved with normal traits and generics.

i.e.

```rust
trait And<Rhs = Self> {
    type Output;
    
    fn and(self, other: FnOnce() -> Rhs) -> Self::Output;
}

impl And for bool {
    type Output = bool;
    
    fn and(self, other: FnOnce() -> bool) -> bool {
        if self { other() } else { false }
    }
}

```

and the desugaring of `&&` could be

```rust
a && b

```

turns into

```rust
And::and(a, || b);

```

* * *

Also isn't removing a trait bound a breaking change? Would that apply in this case (because `Sized` is auto implemented)?

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [November 13, 2018, 5:50am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/12 "2018-11-13T05:50:46Z")

</div>

> [@RustyYato](#):
>
> Also isn’t removing a trait bound a breaking change?

I am not sure. But I think it is not likely, as we don't have negative trait bounds yet.

> [@RustyYato](#):
>
> Would that apply in this case (because `Sized` is auto implemented)?

I think for the type `T` it is implied to be `Sized`, but not for `Self`. However, the source code explicitly requires `Self: Sized` and this is what I want to change.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [November 13, 2018, 6:00am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/13 "2018-11-13T06:00:39Z")

</div>

> [@earthengine](#):
>
> I am not sure. But I think it is not likely, as we don’t have negative trait bounds yet.

Negative trait bounds would make _adding_ a trait a breaking change. Removing a trait bound for a trait could be a breaking change. For example say (in some crazy world) we remove the trait bound `Clone` for `Copy`. Any code that relies on the fact the every type that implements `Copy` also implements `Clone` would break. But with the `Sized` trait I'm not so sure because it is the default and it is auto-implemented.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [November 13, 2018, 6:27am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/14 "2018-11-13T06:27:17Z")

</div>

> [@RustyYato](#):
>
> But with the `Sized` trait I’m not so sure because it is the default and it is auto-implemented.

For traits the default is `?Sized`, but you can transitively infer `Sized`.

This is contrived, but here I'm able to depend on `Into: Sized` to call `uninitialized()`:

```rust
trait Foo: Into<()> {
    fn foo() {
        let x: Self = unsafe { std::mem::uninitialized() };
        std::mem::forget(x);
    }
}

```

So yes, I think removing a `Sized` trait bound is _technically_ a breaking change, though I have no idea if this would come up in a more realistic scenario.

---

<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:31am UTC](https://internals.rust-lang.org/t/mini-pre-rfc-make-into-trait-object-safe/8827/15 "2019-03-25T08:31:09Z")

</div>

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