Description
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);