Why is there no PinRc, PinArc, etc?

Why is ther PinBox but not equivalents for Rc and Arc, or for that matter Vec?

You’re very lucky, @withoutboats posted a sort of reply for this just a few hours ago:

(EDIT: Although it doesn’t cover Vec, I don’t think it’s possible to have a collection of pinned objects similar to Vec, you could probably have some form of bucket allocated linked list as an alternative though).

3 Likes

Nice! I like it.

That actually could potentially add some support for Vec as well, with something like:

impl<T> From<Vec<T>> for Pin<Vec<T>> {
    fn from(pointer: Vec<T>) -> Pin<Vec<T>> {
        unsafe { Pin::new_unchecked(pointer) }
    }
}

impl<P, T> Pin<P>
where
    P: DerefMut<Target = [T]>,
{
    pub fn index_pin<'a, I>(&'a mut self, idx: I) -> Pin<&'a mut I::Output> 
    where 
        I: SliceIndex<[T]>,
        T: 'a
    {
        unsafe {Pin::new_unchecked(&mut self.pointer[idx]) }
    }
}

Of course once you’ve moved the Vec into a Pin, you can’t add or remove elements, since that would move the contents. (So maybe it should be impl<T> From<Vec<T>> for Pin<Box<[T]>> instead?)

I think this would be written

let vec: Vec<_>;
vec.into_boxed_slice()
   .pin()

There’s no reason to support a pin over Vec specifically since Vec can’t be used to pin its contents. (As pushing would move its contents.)

2 Likes

Except that you can't call all the methods like push since you don't have a &mut Vec. I'm pretty sure that @tmccombs is right:

impl<T> From<Vec<T>> for Pin<Vec<T>> { /* ... */ }

is valid (using @withoutboats's new API). I don't think this should be restricted to Box<[T]>, since Vec can provide a lot more, in addition to not requiring a reallocation on creation. Going through the list of methods (just those on Vec, not those on []), it seems to me that clear, truncate, and set_len should work without modification on Pin<Vec> and push, append, resize, resize_with, resize_default, and extend_from_slice can work if they are modified to return errors instead of reallocating when the Vec is at capacity.

It definitely is a more niche use case, and I don't think it would ever be possible to justify a standalone PinVec type in the standard library, but this is one of my favorite aspects of @withoutboats's new API: it allows for these more obscure cases without extra work.

1 Like

So in effect Pin<Vec<_>> would be a Vec<_> that never reallocated (grows bigger)? That actually seems useful separate from the pinning of its contents, though maybe not as useful as a stack vector.

You could implement an interpreter using a Pin<Vec<Byte>> as the stack, and an attempt to reallocate would be a stack overflow, and since the contents are pinned, references are sound. This sounds simultaneously silly, pointless, and fun.

Yes, though it occurs to me that it would actually be valid (if useless? you could just get a new Vec) to reallocate the Vec when it is empty.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.