Good write up! A few comments.
There is clearly an advantage to being able to use my_vec.front <- item over my_vec.push(item), but the change in form is slightly jarring. An implementation detail has become a clear syntactic change even though the semantics are roughly the same. I know that rustc and llvm in general cannot optimize that kind of thing away but perhaps we could introduce a way to mark methods and functions as “placer” functions? Any use of the parameter would not be valid until the item has been placed/initialized within the body. And in fact, perhaps the <- syntax could be used for this within methods.
So specifically what I’m wondering is, is it possible perhaps to add a pragma #[unitialized(arg1, arg2, arg3)] to require the arguments listed in the method be placed before used? This would shelter users from implementation details. It would also change the order of side effects in a significant but in my opinion backwards compatible way.
Of course reimplementing vector.push(item) in terms of an uninitialized marker pragma would break builder patterns, so many of these should be new, “in place” versions of methods, in the same way we have mut versions. vector.push_ip(item) as shorthand.
Admittedly, hidden semantics are not the best choice, but I want to put this idea out here because I really think similar things should look similar, and pushing a value with a temporary stack allocation, and pushing a value without one, should both be transparent. Shouldn’t they?
Alternatively, we already have a very robust notion of lvalues and assignment. Currently, place = value is valid syntax where place is &mut. What’s wrong with extending the notion of lvalues to include places? Then instead of reference = (place <- value) we have reference = (place = value), where assignment returns the reference if it supports it as was mentioned in the RFC.
I am going to reiterate this because I think it is important. The fact that chaining assignment is currently possible but useless, the fact that we have such a flexible notion of lvalues but are not leveraging this concept for an ambitious and serious addition to Rust semantics, and the fact that rather than using existing syntax we have to add new syntax concerns me. I think reinvestigating the possibilities of overloading lvalues to include places is a lot more appealing.
The potential for introducing garden paths is a big deal, to me. To preserve left to right reading, there should be an additional left associative -> operator that does exactly what one might expect.
let reference = value -> some_vec.place();
Obviously this was the advantage of the box in place syntax, but this also means that no new keywords have to be introduced. It’s consistent with the other version. I think it’s quite common in most language constructs with this kind of directional semantics to offer two versions of an operator so one is not preferred over the other.
This is not about changing the syntax. I am just proposing to add a little more to it. I don’t think this will be ambiguous with type context -> because even when writing out closures, there is a clear and unambiguous difference between the places where one might expect an expression and where one might expect a type.