I have originally asked this question here, but it was marked as duplicate, although it duplicates only a part of it in my opinion, so I have created a more specific one:
(An older revision of this answer essentially advised to clone the underlying struct and put it in a new Rc<RefCell<Box<MyTrait>>
object; this was necessary at the time on stable Rust, but since not long after that time, Rc<RefCell<MyStruct>>
will coerce to Rc<RefCell<MyTrait>>
without trouble.)
Drop the Box<>
wrapping, and you can coerce Rc<RefCell<MyStruct>>
to Rc<RefCell<MyTrait>>
freely and easily. Recalling that cloning an Rc<T>
just produces another Rc<T>
, increasing the refcount by one, you can do something like this:
use std::rc::Rc;
use std::cell::RefCell;
trait MyTrait {
fn trait_func(&self);
}
#[derive(Clone)]
struct MyStruct1;
impl MyStruct1 {
fn my_fn(&self) {
// do something
}
}
impl MyTrait for MyStruct1 {
fn trait_func(&self) {
// do something
}
}
fn my_trait_fn(t: Rc<RefCell<MyTrait>>) {
t.borrow_mut().trait_func();
}
fn main() {
// (The type annotation is not necessary here, but helps explain it.
// If the `my_str.borrow().my_fn()` line was missing, it would actually
// be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,
// essentially doing the coercion one step earlier.)
let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));
my_trait_fn(my_str.clone());
my_str.borrow().my_fn();
}
As a general rule, see if you can make things take the contained value by reference, ideally even generically—fn my_trait_fn<T: MyTrait>(t: &T)
and similar, which can typically be called as my_str.borrow()
with automatic referencing and dereferencing taking care of the rest—rather than the whole Rc<RefCell<MyTrait>>
thing.