Get &mut P reference to pointer in Pin<P>

I don't see any way to get a &mut P reference to the pointer in Pin<P>? Obviously such an operation would have to be unsafe, but I think there's at least one valid use case for it.

Suppose you had a Pin<Vec<T>> where T: Unpin . I think it would be safe to push to the Vec , so long as you first check that len < capacity. But you can't do this right now without first unpinning with into_inner and then re-pinning.

In essence, I'm using Pin<Vec<T>> as if it were Pin<Box<[T]>> with a variable length up to a fixed capacity.

Does this make sense? Or am I missing something?

A Pin always wraps a pointer, not the object itself. Are you perhaps trying to convert a Pin<&mut P> into a &mut P? You can do this with into_inner_unchecked.

In this case, you could perhaps use Pin::into_inner?

Edit: Sorry, I overlooked you already mentioned that.

1 Like

@alice and @steffahn, yes, I said that in my OP:

But you can't do this right now without first unpinning with into_inner and then re-pinning.

You do not put Pin around the pinned object directly. You put it around a pointer of some sort to the pinned object.

@alice, in this case Vec is acting as a pointer to a slice, hence my comparison to Box<[T]>.

If you call .as_mut(), it will dereference through the DerefMut impl.

For Pin<Vec<T>> that gets you a &mut T. I'm asking for something that gives you &mut Vec<T>.

Well it gives a &mut [T]. There's no way to do that besides transmuting a &mut Pin<Vec<T>>, which is valid as Pin is marked #[repr(transparent)].

Seems like it might be okay to me too. In the meantime, the unpinning+re-pinning approach should work though for your use case at least, right? Even behind a &mut Pin<Vec<T>> you could temporarily replace the whole Vec to be able to use unsafe_into_inner.

As far as I can tell, there is indeed no general way, not even unsafe, to access the pointer inside through behind e.g. a mut reference. Since Pin is repr(transparent the only way I can thing of at the moment is to use transmute.

Yes, sorry, I typed too quickly. .as_mut() gives &mut [T] in that case.

This is more of a theoretical question about pinning. It seemed like there was at least some reason why you might want to access the pointer P itself, rather than the data. But there's currently no way to do so in the Pin API.

I suppose it could make sense for Vec if you make sure to check the capacity first. I don't think people usually use Pin like this.

Maybe that means it's a bad way to use it? That's kind of why I'm asking. It seems like a valid use case, but maybe there are strong reasons not to do it?

On Discord, I argued that wrapping Vec<T> where T: Unpin in Pin communicates that the allocation is stable, even if T can be moved. @rrevenantt argued it does not, because T: Unpin should indicate that Pin is completely transparent. However, maybe you don't even need T: Unpin.

This is wrong. If T: Unpin, the Pin does nothing. This is also why the unpinning and repinning you mentioned is safe.

One point on the Vec example concretely, I don’t think that [T] is necessarily structurally pinning (unless I’m missing something). There is no way to go from e.g. (Pin<&mut [T]>, usize) to Pin<&mut T> by indexing that I know of. For that reason, I don’t think a Pin<Vec<T>> is of much/any use.

Ok, so remove the requirement that T: Unpin. Does it still make sense? I think so. You could still create at Pin<Vec<T>> with a fixed capacity and add items to it over time, each one remaining pinned.

Right, if you have an Pin<Vec<T>> with T: !Unpin, then the allocation is guaranteed stable from safe code, because safe code can neither access the vector itself or any element inside it. So whatever you use unsafe code to allow is all that is allowed.

For Pin<Vec<T>> where T: !Unpin, couldn't you do .as_ref().get_ref() to get a &[T]? Then you could index as normal, right?

Oh, that's a good point. You still can't get a Pin<&mut T> to any though.

Yes, but you don’t get a Pin<&T> from &[T] or &T. If you just want a &T you don’t need to pin anything.