Since the various “placement new” RFC’s were withdrawn last spring, there doesn’t seem to have been much progress on this issue. Would it be possible to have a much simpler solution that doesn’t require any new syntax or traits?
What if we had a single new library function:
ptr::write_with<T, F>(dst: *mut T, f: F) where F: FnOnce() -> T
which would be equivalent to
write_with would be an intrinsic with special compiler support:
f() is evaluated using
dst for the place context, so f’s result is constructed in-place.
Or in implementation terms: when
f()'s result would be created on the stack and memcpy’d to
dst, it gets created directly in
That’s pretty much it. Library functions would have to be changed to take advantage of this, e.g. to add
Box::new_with that allocate storage before calling ptr::write(), but it’s all ordinary rust code.
Is this sufficient? It’s a whole lot less machinery than the the various
Placer proposals had, but I don’t see what problems those solved that this doesn’t.
An even simpler variation
This could work no new functions at all, by making
ptr::write(dst, src) an intrinsic with special treatment. If src is a value expression, it’s evaluated in a place context with address
This version might be easier to use and would benefit existing code, but it might be surprising that you can’t write a forwarding wrapper for it without changing its behavior, or write your own functions with the same behavior.
vec::push_with etc. would still have to take closures, so
ptr::write_with seems more symmetric.
Dynamically sized types
I think this could work with dynamically sized types, though there might be complication around who tells who what the actual size is and what happens if it’s wrong.
Does this actually make enough guarantees?
I’m not sure. The spec doesn’t say what happens when a value expression is evaluated with a value context. I’m interpreting that silence to mean that no move happens (and that no temporary memory location is allocated, so there would be nowhere to move from). But I’m not 100% sure of that. Since temporary allocation and moves are mostly unobservable to programs, maybe the compiler still does it sometimes?