# Is there movement on &move?

**URL:** <https://internals.rust-lang.org/t/is-there-movement-on-move/12867>\
**Category:** language design\
**Created:** [August 10, 2020, 3:40pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867 "2020-08-10T15:40:04Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 10, 2020, 3:40pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/1 "2020-08-10T15:40:04Z")

</div>

I've run into a number of issues recently that really make me want an &move-like construct (basically, an &mut T that makes the referent behave like it has been moved-from). Specifically, this comes up at the intersection of:

- `dyn`, because explosive monomorphization is bad for microcontrollers.
- `no_alloc`, so no `Box<dyn>`.
- Traits for simple state machine transitions, i.e. what would normally be written as follows:

```rust
trait State1 {
  type Assoc: State2;
  fn foo(self) -> Self::Assoc;
}

```

As a workaround, this winds up getting rewritten into

```rust
trait State1 {
  type Assoc: State2;
  fn foo(&mut self) -> &mut Self::Assoc;
}

type DynState = dyn State1<Assoc = dyn State2>;

```

But, now I'm really sad because I've lost Rust's explicit move-checking and have something that has a closer feel to a C++ move constructor. If I could instead have written

```rust
fn foo(&move self) -> &move Self::Assoc;

```

then I would be less sad while still being object safe: the place I took an `&'a move` winds up behaving like something I took an `&'b mut` of, where `'b` is `'a` extended until that place goes out of scope.

* * *

The most recent discussion I could find on this is [`DerefMove` vs `&move`](https://internals.rust-lang.org/t/derefmove-vs-move/8161), and walking the tree of links doesn't make me feel confident about whether there was any consensus about how to specify this. It also seems to be mostly motivated by building `DerefMove`, whereas the primitive I think I want is something resembling this:

```rust
impl<T: ?Sized> RefCell<T> {
    // Future calls to `borrow` and `borrow_mut` always fail.
    // Unfortunately this is incompatible with `get_mut`. Ugh.
    fn borrow_move(&self) -> &move T;
}

```

At any rate, my question: is this moving forward? Is this a thing other people want/lang-team people care about?

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 10, 2020, 4:39pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/2 "2020-08-10T16:39:51Z")

</div>

I'm not sure about the motivation – why does a state machine need to move from, and if you want to move something, why can't you take it by value? If the reason you can't take it by value is that it is unsized, wouldn't it be more productive to move the unsized locals feature forward instead of adding an entirely new feature?

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 10, 2020, 5:16pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/3 "2020-08-10T17:16:05Z")

</div>

My understanding is that unsized rvalues can't do what I want, which is to make traits which take `self` and return associated types object-safe. That is, given

```rust
trait State1 {
  type Assoc: State2;
  fn foo(self) -> Self::Assoc;
}

```

I want to form the type `dyn State1<Assoc=State2>`.

AFAIK we don't have a story for returning trait objects by value.

> why does a state machine need to move from

"State machine" is probably the wrong word; what I'm building is closer to a linear pipeline that might normally be written like this:

```rust
let first = ...;
let second = first.consume();
let third = second.consume();
// And so on...

```

This enforces a strict order of operations. I don't know of a good name for this idiom. My version is made up of traits.

> and if you want to move something, why can't you take it by value?

Because object safety. As you point out, unsized rvalues solves this, but it does not solve returning a trait object by value.

* * *

Of course, if we've figured out a way to return trait objects that is portable and doesn't do horrible things to the stack, this whole discussion is kind of moot.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 10, 2020, 5:53pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/4 "2020-08-10T17:53:29Z")

</div>

Do I understand correctly that you have one additional requirement/wish, specifically the ability to use non-object-safe traits as trait objects? Because that is orthogonal to operating on values vs. references. (In addition, I don't think it's possible – the object safety rules exist for technical reasons.)

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [August 10, 2020, 6:07pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/5 "2020-08-10T18:07:37Z")

</div>

I was also almost certain that trait objects with associated types can't be implemented for the same reason as generics: You can't monomorphize the generic code without knowing the types at compile-time, but trait objects actively prevent you from knowing the types, so their combination is simply a logical contradiction. AFAIK making this not a contradiction would require a deeply radical change like making all Rust programs have RTTI (run-time type information) _by default_, which obviously isn't going to happen.

I have no idea how `&move` references would help with anything like this.

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [August 10, 2020, 6:14pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/6 "2020-08-10T18:14:33Z")

</div>

> [@mcy](#):
>
> ```rust
> fn foo(&move self) -> &move Self::Assoc;
> 
> ```
> 
> ... the place I took an `&'a move` winds up behaving like something I took an `&'b mut` of, where `'b` is `'a` extended until that place goes out of scope

If I understand this correctly.. I think I may see another user case. Anonymous enums are hotly [debated](https://internals.rust-lang.org/t/ideas-around-anonymous-enum-types/12627) now. What it boiled down for me to (I'm using @eaglgenes101 's [syntax](https://github.com/eaglgenes101/rfcs/blob/2c8e89811a64b139a62d199c5f8e5bd3e852102c/text/0000-anonymous-variants.md)) was a light-weight conversion:

```rust
let a: A = ...;
let ab: (A|B) = a; // we're talking about something akin to Haskell's Either - an enum with 2 members with "names" (A|B)::0 and (A|B)::1; what has just happened could have been spelled let abc = (A|B)::0(a)
let bca : (B|C|A) = ab; // we're talking about an enum with 3 members with "names" (A|B|C)::0, (A|B|C)::1 and (A|B|C)::2; what has just happened is a conversion - data has been copied from ab to bca and discriminant has been changed from 0 to 2 in the process
assert_eq!(bca, (B|C|A)::2(a));

```

So here we copied `ab` to `bca` changing discriminant in the process. But what if we wanted to change discriminant "in place"? Rust would need to forget the old variable and know to "reuse" same memory location as a new variable of a new type. Could `&move` be made useful here?

```rust
let a: A = ...;
let ab: (A|B) = (A|B)::0(a);
let bca : &move (B|C|A) = (&move ab) as &move (B|C|A); // no memory copied, just an in-place update of discriminant

```

> [@Ixrec](#):
>
> I was also almost certain that trait objects with associated types can't be implemented for the same reason as generics ... I have no idea how `&move` references would help with anything like this

@mcy did you mean something like this instead?

```rust
trait State {
  fn transition(&move self) -> &move dyn State;
}

```

---

<div class="post-metadata">

**Author:** ![lordan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lordan/32/2107_2.png) [@lordan](https://internals.rust-lang.org/u/lordan)\
**Post date:** [August 10, 2020, 6:33pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/7 "2020-08-10T18:33:36Z")

</div>

> [@atagunov](#):
>
> ```rust
> let a: A = ...;
> let ab: (A|B) = (A|B)::0(a);
> let bca : &move (B|C|A) = (&move ab) as &move (B|C|A); // no memory copied, just an in-place update of discriminant`
> 
> ```

How can this work if `C` - and thus the whole enum - is larger than `(A|B)`?

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [August 10, 2020, 6:34pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/8 "2020-08-10T18:34:48Z")

</div>

> [@lordan](#):
>
> How can this work if `C` - and thus the whole enum - is larger than `(A|B)` ?

Indeed, it cannot ☹

Wild fantasy: if `bca` was somehow both `&move` and read-only...

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 10, 2020, 10:06pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/9 "2020-08-10T22:06:51Z")

</div>

> [@H2CO3](#):
>
> (In addition, I don't think it's possible – the object safety rules exist for technical reasons.)

I think the particular point that was missed here (which maybe I glossed over) is that given

```rust
trait Foo {
  type Assoc: Bar + ?Sized;
  fn foo(&mut self) -> &mut Self::Assoc;
}

```

we can form the trait object type `dyn Foo<Assoc=dyn Bar>`, even though `dyn Foo` on its own is not a valid type. When writing `dyn Trait`, and `Trait` has associated types, they must be specified up-front (this avoids the RTTI issue you allude to). I get the impression that this is not a well-known feature...

Though the compiler seems to provide a nice error message for it: [Compiler Explorer](https://godbolt.org/z/fsbcK3)

* * *

This is well and good, but unfortunately, this only works when we specify the associated type in positions that are all unsizeable, which means that you can't play the same trick with the following trait:

```rust
trait Foo {
  type Assoc: Bar + ?Sized;
  fn foo(self) -> Self::Assoc; // We need Assoc to be sized!
}

```

See: [Compiler Explorer](https://godbolt.org/z/79dbqY)

The reason I bring up `&move` is because it is one option for fixing this. I could rewrite by trait into something like this;

```rust
trait Foo {
  type Assoc: Bar + ?Sized;
  fn foo(&move self) -> &move Self::Assoc;
}

```

With unsized rvalues, I could straight-up take `self`, but I don't believe I can return an unsized type, so I'm still sad.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 11, 2020, 7:03am UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/10 "2020-08-11T07:03:26Z")

</div>

> [@mcy](#):
>
> I think the particular point that was missed here (which maybe I glossed over) is that […] we can form the trait object type `dyn Foo<Assoc=dyn Bar>` , even though `dyn Foo` on its own is not a valid type

Of course `dyn Foo` is not a type, because it is generic, it's a type-level function. I'm still not sure how this relates to using it by-value vs. by-ref, _if_ unsized locals and unsized by-value moves are allowed, ie. what (and why) would be missing in that case.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [August 11, 2020, 10:28am UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/11 "2020-08-11T10:28:03Z")

</div>

> [@H2CO3](#):
>
> I'm not sure about the motivation – why does a state machine need to move from, and if you want to move something, why can't you take it by value? If the reason you can't take it by value is that it is unsized, wouldn't it be more productive to move the unsized locals feature forward instead of adding an entirely new feature?

I can't talk for the OP, but the reason I personally like ["owning pointers"](https://users.rust-lang.org/t/owning-pointers-could-they-exist-be-helpful/43354) / `&move` is precisely that it allows implementing unsized locals.

Here is a proof of concept manually implementing the feature with `unsafe`, a macro, or by infecting everything with contiuation-passing style:

- [Basic example: ownership properties work as expected](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=84b25c252c48172917109f5ceffe24ef)

- [Advanced example: implementing unsized `dyn FnOnce()` locals](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=c85dfafed953da1208c811e97ea38eae)

* * *

It looks like there even is [an experimental crate out there](https://crates.io/crates/refmove), which does mention the unsized locals alternative.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 11, 2020, 12:21pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/12 "2020-08-11T12:21:18Z")

</div>

I have a problem with that on the level of principle. Unsized locals as a core language element would be a natural extension that could "just" be allowed without requiring any particular explicit _feature_ per se. Unsized locals wouldn't complicate the language either concretely or conceptually. They don't seem like something that should actively be "implemented" – rather, they should be allowed by making the compiler smarter.

On the other hand, adding a completely new pointer type like `&move` would make the language grow and it would require APIs to account for that as well (most prominently, blanket `impl`s for `&T` and `&mut T` would be needed to be augmented with the new type).

This seems like the abstraction would be pointing to the wrong direction, so to speak.

For the pure purpose of owning references, there's already the standard `Box`, `Rc`, etc. types and the [`owning_ref`](https://crates.io/crates/owning_ref) crate.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 11, 2020, 2:21pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/13 "2020-08-11T14:21:52Z")

</div>

> [@H2CO3](#):
>
> _if_ unsized locals and unsized by-value moves are allowed, ie. what (and why) would be missing in that case.

You need to be able to return unsized rvalues. AIUI, we have so far failed to come up with a good ABI for this kind of thing. Unsized rvalues are a simple conceptual solution, but implementing them to behave completely like traditional rvalues is non-trivial.

> [@H2CO3](#):
>
> For the pure purpose of owning references, there's already the standard `Box` , `Rc` , etc. types and the [`owning_ref`](https://crates.io/crates/owning_ref) crate.

I work on microcontrollers that can't malloc (as stated prior, I'm `no_alloc`). If I could throw a `Box` at the problem I wouldn't even be bringing this up.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [August 11, 2020, 6:16pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/14 "2020-08-11T18:16:02Z")

</div>

> [@mcy](#):
>
> Unsized rvalues are a simple conceptual solution, but implementing them to behave completely like traditional rvalues is non-trivial.

Sure, it might well be. I'm still in favor of trying to allow treatment of unsized values (whether named or temporary) just like sized values (and making the necessary effort) instead. Adding `&move` references is non-trivial too. That's not a good argument against unsized moves.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 11, 2020, 8:43pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/15 "2020-08-11T20:43:15Z")

</div>

> [@H2CO3](#):
>
> That's not a good argument against unsized moves.

I still don't see how having `&move` and unsized rvalues were ever implied to be incompatible. I think both would be a fine addition to the language, and arguing about unsized rvalues fails to answer the question, "has there been movement on &move and related proposals". If the answer is "no, unsized rvalues do everything we want already", then so be it, but I would like someone familiar with the &move proposals to answer that question.

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [August 12, 2020, 8:09am UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/16 "2020-08-12T08:09:12Z")

</div>

I'm not sure there is "someone familiar with the `&move` proposals", because AFAIK there never was a "serious" `&move` proposal, in the sense of one that had clear compelling motivation and was fully fleshed out and had multiple regular community members supporting it. Every time I've seen it suggested in the past it was your typical incomplete or unmotivated proposal that we politely explain the incompleteness of and then it goes nowhere. And as this thread has already demonstrated, every problem space I've ever seen `&move` references suggested as a solution for turned out on closer inspection to either not be solved be `&move` references at all or have a far better solution in some unrelated feature.

Perhaps the more interesting question is whether there's been any movement on unsized rvalues. That I can confidently answer with a "no".

---

<div class="post-metadata">

**Author:** ![PoignardAzur](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/poignardazur/32/6464_2.png) [@PoignardAzur](https://internals.rust-lang.org/u/PoignardAzur)\
**Post date:** [August 14, 2020, 5:01pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/17 "2020-08-14T17:01:38Z")

</div>

> [@mcy](#):
>
> You need to be able to return unsized rvalues. AIUI, we have so far failed to come up with a good ABI for this kind of thing. Unsized rvalues are a simple conceptual solution, but implementing them to behave completely like traditional rvalues is non-trivial.

What about RFC-2884?

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mbrubeck/32/174_2.png) [@mbrubeck](https://internals.rust-lang.org/u/mbrubeck)\
**Post date:** [August 14, 2020, 5:02pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/18 "2020-08-14T17:02:51Z")

</div>

Throwing in a link for convenience:

> <https://github.com/rust-lang/rfcs/pull/2884>

---

<div class="post-metadata">

**Author:** ![Jon-Davis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jon-davis/32/5453_2.png) [@Jon-Davis](https://internals.rust-lang.org/u/Jon-Davis)\
**Post date:** [August 14, 2020, 6:22pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/19 "2020-08-14T18:22:55Z")

</div>

Anonymous enums have been brought up so I just wanted to give my thoughts on them. I don't think they are the best solution, although I guess they theoretically could serve a similar purpose. The proposal I have been workshoping, and others as well include the concept of `enum impl Trait` which is essentially an opaque enum generated by the compiler where all variants implement some trait. Currently this is only to return multiple local types from the same function.

```rust
fn some(x : Option<usize>) -> enum impl Fn() -> usize {
    match x {
        Some(v) => || factorial(x),
        None => || 0,
}

```

Although I suppose it could theoretically be used as a return type of a trait function where the enum contains all possible return types of all implementations of a trait.

```rust
trait Foo {
    fn foo() -> enum impl SomeTrait;
}

```

In this situation all implementations would need to register their return type with the trait, then the trait would return some compiler defined enum of all possible variants. While probably not an impossible computation I don't know if it would be a feasible one. This means there would need to be some sort of global state across all crates that would need to maintain this enum as implementations are compiled. There is also a lot of guns aiming at your foot with this approach.

```rust
impl Foo for Bar {
   fn foo() -> impl SomeTrait {
        [usize; 1_000_000] // it's all fun and games until someone does this
   }
}

```

This would however means that the return type of foo() is technically a concrete sized type. Although it would be opaque, you wouldn't know what type it actually is. It's essentially a stack allocated trait object.

I suppose a similar approach could be used with unsized types as well

```rust
fn foo() -> enum of str {
    if random() {
        *"Hello"
    else {
        *"Hello World"
    }
}

let hello : enum of str = foo();
println!(hello)

```

I'll be honest though I don't know enough to tell you if this approach is even doable or not.

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [August 14, 2020, 9:29pm UTC](https://internals.rust-lang.org/t/is-there-movement-on-move/12867/20 "2020-08-14T21:29:31Z")

</div>

Oh, neat. This idea is completely nuts but actually the thing I want. Hopefully this will be the solution I need some day. =)

[Next page](https://internals.rust-lang.org/t/is-there-movement-on-move/12867.md?page=2)
