Skip to content

docs: clarify pointer provenance of Rc::as_ptr() #87862

Open
@y21

Description

@y21

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsA-raw-pointersArea: raw pointers, MaybeUninit, NonNullA-strict-provenanceArea: Strict provenance for raw pointersC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-libsRelevant to the library team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions