Can you get the raw pointer of a pinned Arc?

In Rust there are two ways of accessing data:

  • either in the presence of potential aliasing (&_ reference, e.g., the Deref impl on Arc);

  • or with guaranteed uniqueness (&mut _ reference)

    • This is such a strong guarantee, that any kind of mutation is deemed acceptable, including moving data through ::core::mem::swap / core::mem::replace, etc.

The 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.

With Arc<T> (and 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 get_mut and 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 &mut _.

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 Mutex<_> or 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 Mutex/RwLock, Pin<Arc<Mutex<T>>> does never imply that T is pinned).

3 Likes