pub fn boxed(count: usize) -> AllocationMut<T> where T: Unpin {
let boxed_array = vec![T::default(); count].into_boxed_slice();
let mut pinned = Box::into_pin(boxed_array);
// My guess is that this slice doesn't live as long as it needs to?
let slice_mut = Pin::get_mut(pinned.as_mut());
let memory= NonNull::from(slice_mut);
AllocationMut {
memory,
context: Some(AllocationContext::Boxed(pinned)),
}
}
but I can't figure out what's the right way to create a reference that stays valid for as long as the object is alive (not sure if I worded it in an understandable way). Miri rightfully complains that the pointer is trying to make a reference that doesn't exist.
Not sure what you're saying. The current structure works already with arena allocations, now I wanna be able to create an AllocationMut out of a Box, mostly as an utility for tests.
Box<T> is currently defined to be a unique pointer, just like &mut T. This means that if you borrow it and then move the Box, that move invalidates the borrow. (And no, you can’t get around this by using raw pointers and avoiding references; it’s the Box pointer itself that prohibits aliasing, regardless of what other pointer types are used.) There are cases related to pinning where this is not true, but those are not guaranteed (there is no stable API to ask for that, yet).
For now, you must use something like AliasableBox instead of Box (or do your own allocation). In the future, there may be better options.
Also, there is no value in involving Pin here. Pin is only useful to make contracts between two separately-written pieces of unsafe code; if your public API does not expose any Pins and does not allow T: !Unpin, then there is no point in using Pin inside your module.
Isn't this what Pin is for? To prevent the Box from moving? Anyway, after reading the docs of the Aliasable crate, I think I understand what you're saying. I'll incorporate the changes and see what happens
For some pointer type Ptr<T>, Pin<Ptr<T>> means that the T will not move, not that the Ptr<T> will not move. Pin<Box<T>> owns Box<T> directly, so moving Pin<Box<T>> (as you are doing) is moving Box<T> too.
And because you have T: Unpin, it doesn’t even mean that — Unpin re-enables moving of the value. Pin + T: Unpin does nothing; it exists only so that types which don't need pinning can participate in Pin-using generic code without taking on all of the Pin requirements.
Interesting. I admit I haven't actually used aliasable myself — perhaps we’re both missing something. If not, your best choice may be to manage the allocation yourself — define your own type to own the pointer and deallocate on drop.