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 recieversprepare
with the desired layout. container itself decides how to manage its memory, for example,Box
has two options:reallocate
andreallocate_in_place
... ; - after that we get the pointer from
data
byderef_get
and pass in toderef_set
ofdata_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 differentdrop
path, which isunsafe fn drop(*mut self)
fromDerefGet
is.
[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 DerefSet
ting smth. like [1;10*1024*1024*1024]
) is still there, however:
- The vast majority of use cases deal with
Sized
data =>Layout
returned fromDerefGet::layout
is 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
panic
orhandle_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.