In Rust there are two ways of accessing data:
either in the presence of potential aliasing (
&_ reference, e.g., the
Deref impl on
or with guaranteed uniqueness (
&mut _ reference)
- This is such a strong guarantee, that any kind of mutation is deemed acceptable, including moving data through
Pin is a wrapper used to restrict the power of the latter case: despite the uniqueness of a
Pin<&mut _> reference, mutation is still restricted, to avoid moves on position-sensitive data (
!Unpin), such as self-referential structs.
Hence, when having a
Box<_>, a unique-owner kind of pointer,
&mut _-ness is capable of transitively reaching the pointee (
for<T> Box<T> : DerefMut<Target = T>), and thus having
Pin<Box<T>> is indeed accurate to prevent movement mishaps.
Rc<T>) however, since there is shared / aliased ownership, there is no
impl<T> DerefMut for Arc<T>, and we go back to using the “weak”
&T that does not permit moving the pointee.
- Regarding the
make_mut methods, the former will always fail as long as at least one
Arc remains leaked (i.e., after a call to
Arc::into_raw and before the freeing
Arc::from_raw), and in a similar fashion the latter will always clone the pointee. Hence the one leaked into FFI is never accessed by a
Thus, despite the good intention, what your initial code did seems best. And of course the callback should not mutate the given
context, except through
Sync-hronisation primitive such as
RwLock<_> (in which case, by the way,
Pin would have been giving a false sense of satefy: since the pinning is not structural in a
Pin<Arc<Mutex<T>>> does never imply that
T is pinned).