Alternatively, we split DerefMove into two traits:
/// trait for moving out of container
trait DerefGet: Deref {
/// This return layout info of data stored by container
fn layout(&self) -> Layout;
/// This returns an actual data pointer. Also, `Unique` from `core::ptr` may be used here.
fn deref_get(&self) -> *const <Self as Deref>::Target;
/// This is intended to dispose **empty** container
unsafe fn drop(*mut self);
}
///trait for moving in a container
trait DerefSet: DerefMut {
/// prepare the memory region
fn prepare(&mut self,layout: Layout);
/// move the value in. Here I would like to use `Unique` too.
fn deref_set(&mut self,*mut <Self as Deref>::Target);
}
And the interesting part:
...
let data: Box<[u64]> = ...;
let mut data_moved = Box::new();
*data_moved = *data; // tada! [1]
//let data_moved = box *data //this woun't work as of there is no thing which we `DerefSet` yet. [2]
...
[1] What is actually happening is:
- dereference operator calls
layout, gets it, and calls recieverspreparewith the desired layout. container itself decides how to manage its memory, for example,Boxhas two options:reallocateandreallocate_in_place... ; - after that we get the pointer from
databyderef_getand pass in toderef_setofdata_moved; - the final thing to do is to dispose
data, but because of one of containers fields has been moved out, for soundness it needs a differentdroppath, which isunsafe fn drop(*mut self)fromDerefGetis.
[2] If we go that far, we face the need of Placer trait and placement features, exactly as it used to be in past...
The problem of fallible allocation (can be probably be found when DerefSetting smth. like [1;10*1024*1024*1024]) is still there, however:
- The vast majority of use cases deal with
Sizeddata =>Layoutreturned fromDerefGet::layoutis going to be aconst. - Also, I don't see any adequate way to support fallible allocation without some crazy syntax and some kind of opinionated signaling involved; given the previous bullet I don't think that in such case we need to do anything else than a
panicorhandle_alloc_error.
A Sized data example
let mut b: Box<[u8;10]> = ...;
*b = [10;10]; //Here we used `DerefSet`, layout passing is optimized out.
The worst about this is that we don't have fine grained error handling in case of DerefSet allocation fails.