/// Trait for allowing moving out of custom types
trait DerefMove: DerefMut where Self::Target: Sized {
/// destroys container; doesn't run `drop` of contained value; called instead of Drop::drop
unsafe fn drop_empty(&mut self);
/// dereference to a place with a value. Actual moves happen with that place
fn deref_place(&mut self) -> Place<'_,Self::Target>;
/// should be called each time after a place got from `deref_place()` gets out of scope:
/// * this includes pointer style move-ins;
unsafe fn notify(&mut self) {}
}
Pro:
We go for a more complex desugaring => we can completely avoid the need for &move references;
The desugaring for more complex cases can be altered, so it's guaranteed to not touch stack.
Con:
Cannot handle true DST moves: functions that take them as arguments (dyn FnOnce()) would need to receive them as a pointers => indirection.
Notes:
The motivation behind DerefMove::notify is to allow more complex scenarios than a box;
Dropping: when DerefMove::deref_place gets called it becomes responibility of the caller to dispose a value from gotten place, this includes maintaining drop flags for that place. When holder value gets empty because of move out it doesn't go through plain drop path - it instead goes through DerefMove::drop_empty.
No, I propose to allow destructive moves on arbitrary types by allowing them to return pointers to their held values, so they can be moved in\out later. A value or it's part is considered to be moved out from the call to deref_place until return from notify;
They are called together on moving in a value or its part.
This way place gottten from value that implements DerefMove is considered to be partially initialized when it's content gets moved out, as with Box:
let mut x = Box::new(S {a: 10,b: "a".to_string()});
let b = x.b; // here, x.b is moved out (wow); here `DerefMove::deref_place` has been called
//here x is destroyed through `drop_empty`, right after calling `Drop::drop_in_place(DerefMove::deref_place().ptr as &mut _)`
Example use case for this I imagine is DOMNodeHandle that deref's to DOMElement type; Or building some kind of reactive containers (that know whether they have got anything changed in them). Interacting with handles to buffers not in main RAM (so that notify triggers transfers); Not sure if such an implicitness is justified though.
This is simpler, I don't want to go for any &move references because they can only give us move out functionality (given no linear types).