In general, it's impossible to move a value out of Rc
, since it might be read concurrently from somewhere else.
However, if your code's logic can guarantee that this Rc
is the sole owner of the underlying data, there's an escape hatch - Rc::try_unwrap
, which performs the check at runtime and fails if the condition is not fulfilled. After that, we can easily unwrap the RefCell
(not Ref
!) with RefCell::into_inner
:
pub fn unwrap<T>(last_elem: Rc<RefCell<T>>) -> T {
let inner: RefCell<T> = Rc::try_unwrap(last_elem)
.unwrap_or_else(|_| panic!("The last_elem was shared, failed to unwrap"));
inner.into_inner()
}
Playground
Another possible approach, if you want not to move value from Rc
but to get a copy, would be to go with your original approach, but use clone
instead of deref
:
pub fn clone_out<T: Clone>(last_elem: Rc<RefCell<T>>) -> T {
last_elem.borrow().clone()
}
A side note: looks like you're trying to implement some kind of linked list. This is a notoriously hard problem to do in Rust, since it plays very bad with the single-ownership semantics. But if you're really sure you want to go though all the dirty details, this book is highly recommended.