bodil / im-rs

Assorted immutable collection datatypes for Rust
http://immutable.rs/
Mozilla Public License 2.0
1.49k stars 111 forks source link

Lifetime of chunks from vector::Focus::chunk_at #204

Open dfoxfranke opened 1 year ago

dfoxfranke commented 1 year ago

vector::Focus::chunk_at has a signature of

impl <'a, A> Focus<'a, A> {
    fn chunk_at(&mut self, index: usize) -> &[A];
}

meaning that the lifetime of the returned slice is tied to the lifetime of the focus. I think the return type should actually be &'a [A], i.e. the slice lives as long as the vector we're focusing on. This should be safe because:

  1. The Focus doesn't own any chunk storage; it's all managed by an RrbPool.
  2. The RrbPool won't drop a chunk so long as there exists a Vector which references it.
  3. 'a is the lifetime of the Vector which constructed the Focus.

I see that the implementation of Chunks has an unsafe hack which extends the lifetime of a slice returned from chunk_at by casting it through a raw pointer and back. It seems to me that this shouldn't be necessary and what's returned from chunk_at should already have the appropriate lifetime.

For the meantime I've put this into my code as a workaround:

trait FocusExt<'a, A> {
    fn chunk_at_ext(&mut self, index: usize) -> (Range<usize>, &'a [A]);
}

impl<'a, A> FocusExt<'a, A> for vector::Focus<'a, A>
where
    A: Clone,
{
    fn chunk_at_ext(&mut self, index: usize) -> (Range<usize>, &'a [A]) {
        let (range, chunk) = self.chunk_at(index);
        unsafe { (range, &*(chunk as *const [A])) }
    }
}