Safety of "disjoint vec"

Hi, I just wanted to ask whether the following container which I named DisjointVec, for the lack of a better name, is safe (if it violates any rust aliasing or other rules):

pub struct DisjointVec<T> {
    v: UnsafeCell<Vec<Box<T>>>

impl<T> DisjointVec<T> {
    fn get(&self, idx: usize) -> &T {
        unsafe { &*(*self.v.get()).index(idx) }
    fn get_mut(&mut self, idx: usize) -> &mut T {
    fn push(&self, val: T) {  // <- The immutable self is the most important part
        unsafe { (*self.v.get()).push(Box::new(val)) }

My reasoning would be that the items aren't stored directly in the vector but indirectly via the Box. Therefore when a new element is pushed, the vector's inner allocation may be moved but the contents of the boxes stay at the same address, therefore they don't invalidate exising references.
Is this true or are there any other magic Rust reasons that would make this unsafe?

1 Like

Physical addresses not changing is one thing, but Rust pointers have a nasty property called "provenance", which causes all sorts of "obvious" intuitions break down hopelessly. In this case, the provenance of the returned references is the box in which they are stored, i.e. the returned reference derives from the Box. I therefore think that if the Box itself is moved, then your reference is invalidated as well.

You might be able to work around this using raw pointers and Box::into_raw()/Box::from_raw(), because raw pointers have somewhat looser requirements than references, but I'm not nearly sure and I would advise against doing either that or what you are currently doing.

Instead, you could just put the inner Vec into a RefCell – it's a type that is specifically designed for solving this kind of problem.

It would definitely be sound if you used raw pointers in place of boxes.

1 Like

In fact, you don't need to use raw pointers yourself, you can use an existing box-like wrapper like e.g. aliasable::boxed::AliasableBox - Rust

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.