Rc and internal mutability

Does this mean that my (A)RcBorrow::upgrade is unsound? It's a not too uncommon pattern to allow upgrading from &T where the T is statically known to be behind an (A)Rc to an (A)Rc<T>, and that's what that library is providing a type for.

The implementation currently uses

pub struct $RcBorrow<'a, T: ?Sized> {
    raw: ptr::NonNull<T>,
    marker: PhantomData<&'a $Rc<T>>
}

impl<'a, T: ?Sized> From<&'a $Rc<T>> for $RcBorrow<'a, T> {
     fn from(v: &'a $Rc<T>) -> $RcBorrow<'a, T> {
        $RcBorrow {
            raw: (&**v).into(),
            marker: PhantomData,
        }
    }
}

impl<'a, T: ?Sized> $RcBorrow<'a, T> {
    /// Convert this borrowed pointer into an owned pointer.
    pub fn upgrade(this: Self) -> $Rc<T> {
        unsafe { $Rc::clone(&ManuallyDrop::new($Rc::from_raw(this.raw.as_ptr()))) }
    }

    /// Convert this borrowed pointer into a standard reference.
    pub fn downgrade(this: Self) -> &'a T {
        unsafe { &*this.raw.as_ptr() }
    }
}

As I understand it, we've determined that this way of implementing into_raw is incorrect when using the current Stacked Borrows rules, so my "as_raw" implementation would also be unsound to turn into a &$Rc<T> to clone, as it's lost write provenance over the location of T. (And a unique $Rc<T> can be used to write.)

If I understand correctly, the way to make this sound would be to

  • Provide a $Rc::<T>::as_raw(&self) -> *const T function that uses pointer manipulation instead of Deref,
  • Use that in the implementation of $RcBorrow<'_, T>, and
  • Say that the implicit case of &T -> $Rc<T> where T is known statically to only be allocated behind $Rc is actually unsound (unsafe when used to write).

I'm ok with that for this library, but I know &T -> $Rc<T> is used in the wild.