Given the amount of discussion on this and other pin-related threads, I feel like I really need to come up with a proper proto-RFC based on the new idea, if I have any chance to make it a reality…
…But for now, to respond to @withoutboats:
I could imagine concrete use cases for e.g. &mut Pinned<SomeType>, but then you’ve gained nothing over PinMut<SomeType> because the pinning is still showing up in the API.
The generic use case would look like
fn takes_mut_ref<T: ?Sized>(t: &mut T)
or
trait Foo {
fn takes_mut_self(&mut self);
}
T or Self (respectively) would be instantiated with Pinned<SomeType> – but of course, if you don’t need immovability, it could be any other type. Thus, pinning would not be “showing up in the API”.
The conflation with “unsized” doesn’t actually make sense. Something without a dynamically known size can’t be deallocated, for example. This would imply that we leak all generators, and there’s no reason for it.
For now, as @RalfJung said, PinBox would still be a separate type, and it would use the original type’s deallocation routine.
Nevertheless, the issue you mention is a good justification for having trait Move: DynSized. This way, if, say, a future language extension allowed immovable types to be created by value using ‘placement new’, code compatible with that extension could bound on DynSized but not Move.
Now, I think I was wrong to say that Move could be deferred added later as a backwards compatible extension. In particular – having a fundamental function like size_of_val sometimes panic is not a great situation, so even under just the DynSized RFC, we’d probably want to create a new function that does the same thing as size_of_val, but with an actual DynSized bound, and guaranteed not to panic. But if this new function came with a semantic guarantee (implicit or explicit) that you could use the returned size to move the value, then we’d end up having to change it again if we later made Pinned<T> impl DynSized (or added other types that impl’d DynSized but not Move).
So I think the initial design ought to include a Move trait. There wouldn’t need to be any special compiler semantics associated with it yet, i.e. forbidding moves of !Move types, because for now there would be no way to obtain !Move types by value to begin with. The only effects of Move would be:
- the existing
size_of_val would panic for !Move types, and
- unsafe code using the new version of
size_of_val would be expected not to use it to move objects around unless it separately verified T: Move.