Why do `Vec` and `VecDeque` not implement `Unpin` unconditionally?

I've posted a similar question on Reddit.

Is there a reason for Vec and VecDeque not to implement Unpin if T does not implement Unpin?

My understanding is that Vec<T> is, from a memory perspective, more or less a Box<[T]>. Box does implement Unpin even if the contained value does not. So is this just a case of 'because it hasn't been implemented yet', or would there be a soundness issue?

Except it's polar opposite.

Vector have to move all elements when it needs to grow. And it's not clear how do you plan to avoid that.

You can kinda-sorta-maybe invent a data structure which is similar to Vec but different… but that wouldn't be Vec.

If I didn't misinterpret the docs of Pin, having a Pin<Vec<T>> prevents you from calling any methods on Vec, that require a mutable reference, since Pin only hands out mutable reference to Deref::Target, so &mut [T]. Therefore you could not call any methods that would trigger a reallocation, right?

Umm...

The very first phrase of the documentation which you link to:

This is a wrapper around a kind of pointer which makes that pointer “pin” its value in place, preventing the value referenced by that pointer from being moved unless it implements Unpin (emphasis mine).

Yes, you can not call these mutating methods precisely because Vec is not Unpin.

Otherwise it would have been trivial to take Vec from Pin and call them.

With which method though?

Maybe I'm missing something really obvious, for me it seems like Pin<Vec<T>> where T: !Unpin as well as Pin<Vec<T>> where T: Unpin would not allow calling any methods on Vec that would lead to a reallocation.

Also here it says 'preventing the value referenced by that pointer from being moved unless it (the pointed-to value) implements Unpin'. So if I'm not mistaken, this sentence does not refer to the pointer type, only the pointed-to type.

Sorry, you are right.

It's a bit more subtle. You can probably read the documentation or this thread.

The key to understanding are probably these two things:

  • Anything can be Unpin if it wants to.
  • For implementing T: Unpin soundly, the thing to keep in mind is that you must not also implement some kind of Pin<&mut T> -> Pin<&mut SomeField> projection.

In case of Vec it's not clear whether you want to to implement Unpin for the Vec or, alternatively, want to do projections.

Since both can be useful and it's unclear which one is “right” doesn't provide either.

For you own Vec types you can do any of these two choices.

2 Likes

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.