I tried to get a reference-counted Rc<Foo>
from a hash map and put it into a different container (Vec<Foo>
).
Thought this would work (by incrementing the reference count), but instead I got an "expected struct std::rc::Rc
, found reference" error.
How do I convert an &Rc<Foo>
to a Rc<Foo>
?
More info:
struct Foo();
let mut foo : HashMap<usize, Rc<Foo>> = HashMap::new();
let mut bar : Vec<Rc<Foo>> = Vec::new();
foo.insert(0, Rc::new(Foo()));
if let Some(x) = foo.get(&0) {
bar.push(x); // expected struct `std::rc::Rc`, found reference
// note: expected type `std::rc::Rc<Foo>`
// found type `&std::rc::Rc<Foo>` rustc(E0308)
}
I get that the hash map returns a reference to the value it owns. But dereferencing it doesn't work: both if let Some(&x)
and bar.push(*x);
result in a "cannot move out of borrowed content".
Curiously, adding a type annotation changes the error to "cannot move out of an Rc
":
let x : &Rc<Foo> = x;
bar.push(*x); // cannot move out of an `Rc` rustc(E0507)
I need to store a reference to the same object, and not to a copy, so I avoided the .clone()
"escape hatch".
To convert an &Rc<Foo>
-> Rc<Foo>
, use Rc::clone()
, which gives you an Rc object of your own, increasing the reference count under the hood:
let ref_to_rc: &Rc<Foo> = &Rc::new(Foo());
let new_rc: Rc<Foo> = Rc::clone(ref_to_rc);
rc.clone()
is equivalent to Rc::clone(&rc)
, but idiomatic Rust uses the latter to make it clear that the code only increases the refcount, not performing a deep copy of the data like some other implementations of .clone()
do. (Though in some scenarios involving traits you might need to revert to ref_to_rc.clone()
.)
The errors above were about Rust refusing to do the copy implicitly. Why is std::rc::Rc<> not Copy? has an explanation of why it behaves like that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With