Reputation: 3401
I have a function that takes in a Vec<String>
value. I want to use this function on values contained inside my_ref
, so I need to extract a Vec<String>
out of a Rc<RefCell<Vec<String>>>
.
I thought I could do this by dereferencing a borrow of my my_ref
, just like I would for a Rc<RefCell<f32>>>
or Rc<RefCell<i32>>>
value:
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
let my_ref = Rc::from(RefCell::from(vec![
"Hello 1".to_string(),
"Hello 2".to_string(),
]));
let my_strings: Vec<String> = *my_ref.borrow();
let count = count_strings(my_strings);
}
fn count_strings(strings: Vec<String>) -> usize {
strings.len()
}
But doing so results in a dereferencing error:
error[E0507]: cannot move out of dereference of `Ref<'_, Vec<String>>`
cannot move out of dereference of `Ref<'_, Vec<String>>`
move occurs because value has type `Vec<String>`, which does not implement the `Copy` trait
So then, how do I properly extract a Vec<String>
from a Rc<RefCell<Vec<String>>>
?
Upvotes: 1
Views: 642
Reputation: 3435
RefCell::borrow
returns a reference, not an owned value, that's why you having such an error. I can name two different solution for that problem.
Rc
to exclusively-owned typeRc::try_unwrap
is able to check, whether there's other references to the data. If it's the only one, it can be safely converted to the inner type. Then, an owned RefCell
can be converted into its inner via into_inner
function.
let my_ref = Rc::from(RefCell::new(vec![..]));
let inner: Vec<_> = Rc::try_unwrap(my_ref).expect("I hereby claim that my_ref is exclusively owned").into_inner();
If for some reason you want to grab inner value that is already referenced, you may consider replacing it. Note, that you need to create a appropriate value for the type (i.e. with trait Default
). Here's the example:
let my_ref = Rc::from(RefCell::new(vec![..]));
let inner: Vec<_> = my_ref.borrow_mut().take();
// or
let inner: Vec<_> = my_ref.borrow_mut().replace(vec![]);
Upvotes: 2