# Pre-RFC: become-assignments for reliable RVO/DPS

**URL:** https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363
**Category:** language design
**Created:** [July 15, 2015, 5:17pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363 "2015-07-15T17:17:41Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 15, 2015, 5:17pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/1 "2015-07-15T17:17:41Z")

</div>

## Motivation

RVO/DPS is an optimization that avoids allocating unneeded stack temporaries in assignments. For example, in the C code

```rust
#include <stdlib.h>
struct big { int data[1<<30]; };
void poke(struct big *b);
void foo() {
    struct big *s = malloc(sizeof(*s));
    *s = (struct big){{[163]=42}};
    poke(s);
}

```

translates into this assembly code:

```rust
    pushq %rbx
    movabsq $4294967296, %rdi
    call malloc
    movabsq $4294967296, %rdx
    movq %rax, %rbx
    movq %rax, %rdi
    xorl %esi, %esi
    call memset
    movl $42, 652(%rbx)
    movq %rbx, %rdi
    popq %rbx
    jmp poke

```

and no 4GB temporary `struct big` is allocated on the stack. As this optimization can reduce the required stack size by arbitrary amounts, it has a significant semantic effect (similarly to tail call optimization).

However, RVO/DPS-translation in Rust is currently relatively fragile and occurs only in restricted circumstances. The `in/box` proposal has a higher-level interface to it, but lacks a low-level interface (pnkfelix’s draft implementation access it via a hack). It would be desirable to have a decent low-level interface.

The main reason for the fragility of RVO/DPS is that the destination must not be aliased during the expression’s evaluation - this makes it not work in the `*p = φ` case, as raw pointers have no aliasing information.

## Detailed Design

Add the become-assignment expression.

### Syntax

```rust
expr |= '*' 'become' expr '=' expr { ExprBecome(Expr, Expr) }

```

### Typing

```rust
forall type T, expr DEST, expr EXPR.
DEST: *mut T, EXPR: T, T: Sized
------------------------------------
*become DEST = EXPR : ()

```

### Semantics

become-assignment assigns the value of its expression to its destination without running destructors on the destination. The memory pointed-to by the destination is considered to be borrowed mutably during the evaluation of the expression (i.e. touching it will cause UB). become-assignment should be translate the expression in DPS style to the destination, and in any case must not allocate large temporaries.

Of course, become-assignment consumes the result of its expression, and is unsafe as it writes to a raw pointer.

## Alternatives

We may want to introduce become-assignment for (safe) mutable references (in that case, the mutable borrow of the destination should of course be tracked by borrowck). In that case, we _do_ have to run the destructors on the destination _before_ the expression is evaluated, which would be inconsistent with the raw-pointer version. Also, it is unclear that this would be useful (users, this is your opportunity).

## Drawbacks

Increased complexity.

## Unresolved Questions

Syntax bikeshedding. Do we want to allow the `&mut` form?

---

<div class="post-metadata">

### Author: ![jnicklas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jnicklas/32/414_2.png) [@jnicklas](https://internals.rust-lang.org/u/jnicklas)
#### Post date: [July 15, 2015, 10:19pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/2 "2015-07-15T22:19:05Z")

</div>

There’s an RFC which has already been accepted, which solves the same problem, I think: [https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md](https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md)

---

<div class="post-metadata">

### Author: ![bwo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bwo/32/5414_2.png) [@bwo](https://internals.rust-lang.org/u/bwo)
#### Post date: [July 15, 2015, 10:46pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/3 "2015-07-15T22:46:14Z")

</div>

"The in/box proposal has a higher-level interface to it, but lacks a low-level interface (pnkfelix’s draft implementation access it via a hack). "

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 15, 2015, 11:12pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/4 "2015-07-15T23:12:51Z")

</div>

Exactly.

---

<div class="post-metadata">

### Author: ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)
#### Post date: [July 16, 2015, 12:28am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/5 "2015-07-16T00:28:09Z")

</div>

The primary difference between this and `=` is that it does not run destructors, right?

---

<div class="post-metadata">

### Author: ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)
#### Post date: [July 16, 2015, 12:31am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/6 "2015-07-16T00:31:36Z")

</div>

Also, to clarify, the hack in question is having special code in trans for the “initialization intrinsic” (`move_val_init` (or whatever we call it these days)?

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 16, 2015, 6:11am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/7 "2015-07-16T06:11:17Z")

</div>

The difference is both that we don’t run destructors and that we have the noalias property (ptr assignment doesn’t AFAIK). This is indeed a replacement for `move_val_init`, which is an intrinsic that does not behave like a function.

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [July 16, 2015, 10:03am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/8 "2015-07-16T10:03:25Z")

</div>

FWIW, I think the `&out` (or `&uninit`, whatever) references which have been previously proposed would also provide the same functionality (in a safe way)?

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 16, 2015, 10:27am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/9 "2015-07-16T10:27:20Z")

</div>

If we could figure out a way to make them work with unwinding, then sure. I think we should probably have this feature be unstable until we decide what to do with these.

---

<div class="post-metadata">

### Author: ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)
#### Post date: [July 16, 2015, 1:50pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/10 "2015-07-16T13:50:33Z")

</div>

Yes, I see. While I am not a fan of magic intrinsics in general, I don’t see that this use case merits new syntax, at least not as presented. I’d like some evidence that it will be widely used. New syntax carries a very high price in terms of the perceived complexity of the language (accurate or not); much higher than a caveat on a random intrinsic you can find in the back of the language reference.

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 16, 2015, 4:42pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/11 "2015-07-16T16:42:40Z")

</div>

That’s why I wanted it to be perma-unstable syntax at first (maybe make it into HIR-only syntax?)

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 21, 2015, 5:28pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/12 "2015-07-21T17:28:44Z")

</div>

@eddyb discovered this can essentially be done by `unsafe { ptr::write(&mut p, val) }` (with optimizations)

---

<div class="post-metadata">

### Author: ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)
#### Post date: [July 21, 2015, 6:41pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/13 "2015-07-21T18:41:43Z")

</div>

I don’t really understand why a separate low-level interface is needed. Per the [RFC](https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md), couldn’t you easily write a trivial `Placer` that just takes a raw pointer and returns it again from the `pointer` method? (That is, under the assumption that the actual `in place { block }` syntax will be directly implemented by the compiler and thus not need any special intrinsic or operator to do its job.)

---

<div class="post-metadata">

### Author: ![arielb1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arielb1/32/3044_2.png) [@arielb1](https://internals.rust-lang.org/u/arielb1)
#### Post date: [July 22, 2015, 3:56pm UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/14 "2015-07-22T15:56:32Z")

</div>

That’s a decent suggestion too (cc @pnkfelix).

---

<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:24am UTC](https://internals.rust-lang.org/t/pre-rfc-become-assignments-for-reliable-rvo-dps/2363/15 "2019-03-25T08:24:50Z")

</div>

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