Can `Pin` container replace/remove elements safely

I've implemented a custom PinVec, which is a Vec with pinned element. I'm trying to figure out if the following get/set interface is sounded.

struct PinVec<T> { ... }

impl<T> PinVec<T> {
  fn get(&self, idx: usize) -> Pin<&T> { .. }
  fn get_mut(&mut self, idx: usize) -> Pin<&mut T> { .. }
  fn push(&mut self, val: T) { .. }

  fn set(&mut self, idx: usize, val: T) { .. }
  fn remove_last(&mut self) { .. }
}

Particularly, are set and remove_last sound, do they require T: Unpin or unsafe? The relevant part seems to be this Drop Guarantee section std::pin - Rust. Though I don't know if that reads as I can drop old values safely and T will handle notifications by itself.

The drop guarantee only requires you to call drop_in_place on the pinned value before replacing it or considering it removed from the PinVec.

You can even implement PinVec::set in terms of PinVec::get_mut and Pin::set, neither of which requires T: Unpin or unsafe.

.push() breaks everything here. Pushing a new element into a Vec may cause a reallocation of existing elements, which moves the T elements. This breaks the Pin guarantee provided via the other methods.

2 Likes

One may do the same thing std::deque does in C++, but yes, obviously PinVec couldn't be based on Vec, I hope @lantua understands that.

Yea, that's why I can't just use Vec. I'll just use a lot of Box<[T]>.

1 Like