docs: clarify pointer provenance of Rc::as_ptr() (original) (raw)
It is unclear whether it is valid to mutate the *const T returned by Rc::as_ptr() without looking at or relying on implementation details (edit: assuming there is no other Rc or Weak to the same T, aka. strong count is 1 and weak count is 0).
A quick look at the function signature in the documentation may suggest that, given it takes a &Rc<T> and returns a *const T, it should be UB to mutate. However, Rc<T> itself does not own the T, so &Rc<T> ≠ &T.RcBox<T> (private, impl. detail) does own the T, and Rc<T> always contains a mutable pointer to the RcBox, so the type of reference in the receiver (&Rc<T> vs &mut Rc<T>) should be irrelevant as to whether it is valid to mutate the *const T.
I believe it is valid to mutate the *const T as Rc is currently implemented, despite only having a shared reference to Rc<T> and the pointer being const (AFAIK *const vs *mut is just "cosmetic", what matters is how the pointer was obtained)
This relies on implementation details of Rc<T> and I feel like this situation should be documented.
(The same applies to Arc::as_ptr())
use std::rc::Rc;
let foo = Rc::new(1u8);
unsafe { // Valid? Relies on implementation details let foo_ref = &mut *(Rc::as_ptr(&foo) as *mut u8); *foo_ref += 1; };
println!("{}", foo);