Any guarantee for validity of multiple `Rc::from_raw()` calls for single `Rc::into_raw()`?

I'd like to clone Rc<T> from *const T created by Rc::into_raw(), without touching ownership of the original Rc behind the raw pointer. I.e. what I wanted is:

fn clone_raw1(raw: *const T) -> Rc<T> {
    // Restore `Rc` temporarily to clone.
    let original = unsafe { Rc::from_raw(raw) };
    // Clone `Rc`.
    let cloned = Rc::clone(original);
    // Make it pointer again so that the caller can continue using `raw`.
    let raw2 = Rc::from_raw(original);

    // I wish they were always identical...
    assert_eq!(raw, raw2);
    cloned
}

I checked the std reference but I don't find any guarantees of raw == raw2. (I think they would be always the same in the current std implementation, but I need the guarantee.)

So I searched issues and found Feature: Rc::clone_raw (and for Arc) (#48108) and Add strong_count mutation methods to Rc (#83476), and then next question arises: am I allowed to call Rc::from_raw() multiple times for a pointer created by single Rc::into_raw() call?

fn clone_raw2(raw: *const T) -> Rc<T> {
    // Obviously OK, as long as `Rc` behind `raw` is not yet dropped.
    unsafe { Rc::increment_strong_count(raw) };
    // Possibly more than one `Rc::from_ptr` for single `Rc::into_raw`...
    // Is it allowed?
    unsafe { Rc::from_raw(ptr) }
}

fn main() {
    let raw = Rc::into_raw(Rc::new("hello".to_owned()));
    let rc1 = clone_raw2(raw);
    let rc2 = clone_raw2(raw);
    let rc3 = clone_raw2(raw);
    let rc0 = Rc::from_raw(raw);
    // Four `Rc::from_raw()` calls for single `raw` pointer!
}

I think it is probably allowed (in the current std implementation), but I cannot find documentation that allows and guarantees it explicitly. All examples for Rc (https://doc.rust-lang.org/1.70.0/std/rc/struct.Rc.html) are carefully(?) written in a way every Rc::from_raw() call corresponds to different Rc::into_raw().

So my question is:

  • Is it allowed to call Rc::from_raw() multiple times for a pointer created by single Rc::into_raw(), assuming the strong count is appropriately incremented?
  • Is there any documentation that describes about that explicitly?
  • Additional question: Is there any guaranttee that the multiple Rcs sharing the single object return the identical pointer by Rc::into_raw()?
    • See assert_eq! in the clone_raw1() example.

I don't know about how clearly this is or isn't guaranteed from the documentation, but the clone_raw2 code is what I would have written for this, too (except it should probably be an unsafe fn).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.