I might be wrong, but I think this all can be implemented quite safely..
struct OwnRef<'out, T : 'out + ?Sized> {
ptr::NonNull<T>,
PhantomData<&'out mut T>,
}
impl<'out, T : 'out + ?Sized> OwnRef<'out, T> {
// compiler magic: after this is invoked normal dropping is suppressed on the object referenced
// it is if we move out of that object but the memory region remains borrowed mutably
// this means that on the one hand the memory area is not usable anymore except through
// this OwnRef but it also means that the owner has the obligation not to deallocate it
// for the duration of the lifetime
pub fn new(r : &mut T) -> Self {
OwnRef{ptr : ptr::NonNull::new(r as *mut T)}
}
}
impl<'out, T : 'out + ?Sized> Drop for OwnRef<'out, T> {
fn drop(&mut self) {
unsafe{ ptr::drop_in_place(self.ptr.as_ptr()); }
}
}
impl<'out, T : 'out + ?Sized> Deref for OwnRef<'out, T> ...
..DerefMut..
I believe the idea of having &own
references has been around for a while. I also believe the semantics of those has been understood as I described above. I honestly don't see the reason the concepts of owning memory (having the obligation and means to deallocate it) and owning content of that memory (say owning a block of heap referenced from the said memory) cannot be decoupled.
Surely Drop::drop()
can be invoked long before the actual stack frame is popped or free
invoked on the relevant block of heap memory. Surely Drop::drop()
can be invoked from a few stack frames down from where the memory is deallocated. Provided that Drop::drop()
is not invoked after the memory is actually deallocated. And provided that after Drop::drop()
that memory remains unusable.
The lifetime engraved in &out
(aka OwnRef
) reference is the lifetime of memory. Of course whoever holds such an &own
(aka OwnRef
) cannot hold onto it/use it longer than the lifetime engraved in the type. So he has to dispose of his ownership (dispose of that OwnRef
) before that lifetime expires - and that's when drop
gets called. But this can happen a few stack frames down from the stack frame in which the memory is actually allocated.
I believe the idea has been around for a while and is uncontroversial. I'm actually surprised by the amount of conversation we're having about it. It appears very obviously safe and correct to me. I was under impression it is not yet implemented chiefly because nobody felt like it would yield enough benefit.
Yes indeed this blurs the line between a reference and a value. This is indeed what I have brought up for discussion. Philosophically what does an identifier that refers to a struct on the stack signify? It can be viewed as signifying the address of such a struct. From this point of view 'a S
identifier would signify just the same - but a few stack frames up. Is that good or bad? Open to opinion it seems to me.
In other words an identifier that refers to a struct on stack is an lvalue
. So this identifier referencing 'a S
is an lvalue
as well.
What do I want? Good question Always good to ask. I guess I want to talk, to ponder, to consider possibilities. I almost have no horse in this race but I really wanted to discuss/consider to death what @petertodd suggested in the neighboring topic. I've taken his idea and put my spin on it. What would it feel like if it really was implemented?
In the process I did answer the question of what it might be good for: