I have traits Child
and Super
where Super
is a supertrait of Child
. I have a function that will get an instance of Rc<RefCell<dyn Child>>
as a parameter, but I need to pass it to a function that needs a Rc<RefCell<dyn Super>>
as parameter. The following code should illustrate the situation: (I'm trying to implement the use_child
function such that it will call the use_parent
function):
use std::{rc::Rc, cell::RefCell};
fn use_parent(parent: Rc<RefCell<dyn Super>>) {
// Use the parent functionality
}
fn use_child(child: Rc<RefCell<dyn Child>>) {
// I tried this, but it won't compile
use_parent(child as Rc<RefCell<dyn Super>>);
}
trait Super {}
trait Child: Super {}
The compiler gives the following complaint:
error[E0605]: non-primitive cast: `std::rc::Rc<std::cell::RefCell<(dyn Child + 'static)>>` as `std::rc::Rc<std::cell::RefCell<dyn Super>>`
--> src/lib.rs:9:16
|
9 | use_parent(child as Rc<RefCell<dyn Super>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
I read the suggestion of the compiler, but could only come up with use_parent(Rc::from(child))
, which won't compile either.
From the answers of the related question (Why doesn't Rust support trait object upcasting?), it appears that doing what I'm trying is not (directly?) possible due to vtable problems. Another answer of that question also showed the following work-around:
trait Base: AsBase {
// ...
}
trait AsBase {
fn as_base(&self) -> &Base;
}
impl<T: Base> AsBase for T {
fn as_base(&self) -> &Base {
self
}
}
Unfortunately, I can't just use this work-around because everything is wrapped inside Rc
and RefCell
, which makes my question different from the other question.
The best work-around I could come up with was passing both a Rc<RefCell<dyn Child>>
and a Rc<RefCell<dyn Super>>
to the use_child function where both Rc
's point to the exact same cell. This would solve the problem, but requires me to always keep an extra Rc
. Besides, this feels quite dirty.
So does anybody know a better solution?