# Removal of all unstable placement features

**URL:** <https://internals.rust-lang.org/t/removal-of-all-unstable-placement-features/7223>\
**Category:** announcements\
**Created:** [April 3, 2018, 10:15pm UTC](https://internals.rust-lang.org/t/removal-of-all-unstable-placement-features/7223 "2018-04-03T22:15:39Z")\
**Posts on this page:** 1\
**Showing post:** 17

<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:** [April 6, 2018, 12:33am UTC](https://internals.rust-lang.org/t/removal-of-all-unstable-placement-features/7223/17 "2018-04-06T00:33:56Z")

</div>

> [@gnzlbg](#):
>
> How would compilation under a different model that solves this problem scale?

I'm not proposing that the compiler would make decisions based on the _body_ of `push`, but based on some attribute or other marker on the declaration of `push`. I know that's vague, but I wanted to leave open the space of possible designs.

Here's a strawman for a more specific design:

Add a new trait as an alternative for the `Fn` trait for functions (or function-like objects) that want to allow constructing their arguments in place – call them "placer functions", and call the trait `PlacerFn`. (There probably also need to be `PlacerFnMut` and `PlacerFnOnce`.) In the simplest case, implementations would manually impl this trait (XX: but how to make this work with method syntax?). However, there might be some potential to allow wrapper functions that delegate to placer functions to be written as normal functions with an attribute attached, as long as they satisfy certain conditions and have the compiler generate an impl automatically.

A placer function receives its arguments in stages, through a series of calls: that way, given a function like `Vec::insert(&mut self, index: usize, element: T)`, the implementation can receive the `index` before returning a place in which to construct the `element` (so it could shift existing elements forward, and return a pointer to the newly vacated `&vec[index]`). As it happens, when these kinds of functions have more than one argument, they usually take the value as their last argument, so we can simplify things by requiring arguments to be received in order from left to right; this also avoids messing with the order of evaluation on the caller side.

Here's a possible definition of the `PlacerFnOnce` trait:

```rust
// These names all suck and should be bikeshedded
trait PlacerFnOnce<UpfrontArgs, PlacedArg, RemainingArgs> {
    type Output;
    type Place: Place<PlacedArg> + PlacerOrNormalFnOnce<RemainingArgs, Output=Output>;
    extern "rust-call" fn provide_arguments(self, UpfrontArgs) -> Self::Place;
}

```

Whereas the Fn trait has one generic parameter, `Args`, representing a tuple of all the arguments, this has three, splitting the argument list into three parts:

1. `UpfrontArgs` is a tuple of any arguments that don't need to be constructed in place, but should be passed up front, by value – such as the `index` parameter from `Vec::insert`.
2. `PlacedArg` is the argument that needs to be constructed in place.
3. `RemainingArgs` is a tuple of the rest of the arguments, if any, which will be provided in a subsequent call. (There always needs to be a subsequent call, even if there are no more arguments: the call will also act as the equivalent of `InPlace::finalize`, signaling that the in-place construction has completed successfully.)

[An alternative design could stick with a single `Args` parameter and use associated types to determine how to split it into parts; this would help avoid ambiguity, but would make the trait definition look a bit more complicated.]

The return value of `provide_arguments` must impl two traits: `Place<PlacedArg>`, which is the same as the existing, soon-to-be-deprecated `Place` trait (i.e. it provides a pointer to place the argument into), and `PlacerOrNormalFnOnce`, for the subsequent call.

`PlacerOrNormalFnOnce` is a trait that has blanket impls for types that impl _either_ `PlacerFnOnce` or the normal `FnOnce`. (This can be achieved with specialization, but would require the lattice rule, or some other mechanism, to handle cases where someone tries to impl both `PlacerFnOnce` and `FnOnce` on the same type.) The compiler could also use this trait to decide which of `PlacerFnOnce` or `FnOnce` to use for a function call in the first place.

So the function call desugaring takes three steps:

1. Call `provide_arguments` with the upfront arguments to obtain a `Place`;
2. Get the pointer from the `Place` and construct the argument in place;
3. Do a recursive call on the `Place` object itself with the remaining arguments. (This is always done by-value through `PlacerOrNormalFnOnce`, even if the original call was through `PlacerFn` or `PlacerFnMut`, so that the callee can take ownership of the `Place`.)

If the `Place` itself impls `PlacerFnOnce`, that indicates that there's another argument somewhere in the list that needs to be constructed in place, so it goes through the whole process again. On the other hand, if the `Place` impls normal `FnOnce`, that's the end of the line: it will be called with the remaining arguments and produce the final function return value.

Similarly to the existing `<-` behavior, if evaluation of an in-place argument diverges (i.e. it panics, executes `break` or `return`, etc.), then the `Place` will be dropped instead of being passed by value into a method call; the `Drop` impl should handle reverting the container to its previous state.

Also note that the `PlacerFn*` traits would not be usable as trait objects, at least not unless you provided the `Place` associated type up front as part of the trait object type. That's probably not the end of the world; I'd _love_ to see an expansion of object safety in general, but that's a quite separate topic.

TL;DR: basically the same thing under the hood as the existing `Placer`, but implicit in function calls.

---

_[View the full topic](https://internals.rust-lang.org/t/removal-of-all-unstable-placement-features/7223)._
