A question about the core::marker::PhantomPinned


#1

Is it make sense to derive Copy for it? It is weired because a type being !Unpin + Copy simply does not make sense. If the copied object works well, it doesn’t have to be !Unpin, otherwise there is no reason to make it Copy.

Did I miss anything? If this is just an mistake, we still have time to fix it in beta channel before leak to stable.


#2

For some intrusive data structures theres no problem with being Copy, because the addresses we care about not invalidating are not inside the struct itself.


#3

Yes I know this can be the case.

However even in such a case, the !Unpin trait bound didn’t actually garantee anything - anything that is Copy cann’t be Drop, and then you are completly OK to copy the object to somewhere else and ignore the original, this makes a legal way to move the object, even when it is by definition illigal.

In other words, if copying the object does not cause UB, moving the object can never UB, because moving is just copying plus marking the original invalid.


#4

You’re right that you can’t implement a destructor like would be needed to remove the item on invalidation in a Copy type. But in the abstract, barring that limitation which we have imposed, you’re wrong when you say this:

If you could have a Copy type with a destructor, the destructor could tell a global set of nodes to remove it if it is a member. The global set is storing members by address; copied objects would not be members of the set. To add it to a set you would put it into a pin. This would guarantee that objects would always be removed from the set when they went out of scope, while allowing you to copy them and later re-add them to a set. Right now you have to call clone on members if you implement this because members also need a destructor, but cloning is just memcpy.

In any event there’s nothing unsafe about a type being !Unpin and Copy and I do not think we should change anything, even if a use case is hard to fathom.


#5

I am brainstoming about what I can do with a Unpin + Copy but not a !Unpin + Copy.

So let me define

#[derive(Copy, Clone)]
struct PinnedI32(i32, PhantomPinned);

This is just a newtype of i32. Now we can do

let mut pv = Box::pin(2);
let p = pv.as_mut().get_mut();
*p=3;

but not

let mut pv = Box::pin(PinnedI32(2));
//illigal beacause `PinnedI32` is not `Unpin`
//let p = pv.as_mut().get_mut(); 
//*p = 3;

So they do have difference. By change the data from a normal Unpin + Copy type to !Unpin + Copy, the data was effectively freezed after a Pin pointer being created: now you need unsafe code to mutate the value.

Therefore the conclusion is that !Unpin + Copy means the pinned value is garanteed immutable until Droped by the container?