I have a Box that gets taken control of by an outside runtime.
when it is offered back to rust it is in embedded in an allocation on the other runtime heap.
so it would be natural to refer to its location via a raw pointer or reference.
I need ownership and .forget() will be invoked on it but since it is non-Copy
the compiler disallows a de-referencing.
my question is how does one get back ownership of the trait object without copying?
If you know the other side (and generally nothing else) won't touch the pointee anymore (which is required to get true ownership of it), then you can ptr::read() a copy of it. That is, the following is sound:
let foo: Foo = Foo::new();
let ptr_to_foo: *mut Foo = ffi::taketh_and_giveth_back(foo);
// the pointee `Foo` will no longer be accessed by the FFI, but the pointer
// itself does not come from a `Box` allocation, so `Box<Foo>` is not right.
let foo: Foo = unsafe { ptr_too_foo.read() };
stuff(foo);
Justification
The FFI side won't be dropping stuff unless told explicitely, so you can see that as if all the fields of all structs were wrapped inside ManuallyDrop<_>.
The heap allocation from FFI could be seen as an FFIBox<_> smartpointer that implements DerefMut (by virtue of exclusive ownership).
The pointer to our Foo thus originates from a FFIBox<StructWithField<ManuallyDrop<Foo>>>.
By virtue of ownership over such FFIBox, and using DerefMut, we can get a &mut ManuallyDrop<Foo>.