this is kind of a follow up question from this: Rust dynamic cast trait object between different taits
The solution provided there works really well when we use references for trait objects.
This time I was trying to do the same with Rc pointers. For example
- I have a super trait named
TraitAB
and 2 traits namedTraitA
andTraitB
- So when I first create a trait object of type
TraitAB
instead of using aBox
, now I use anRc
pointer. - I need a variable of type
TraitA
to be a reference ofab
Here I made a very minimal example:
use std::rc::Rc;
trait TraitAB : TraitA + TraitB {
fn as_a(&self) -> Rc<dyn TraitA>;
fn as_b(&self) -> Rc<dyn TraitB>;
}
trait TraitA {}
trait TraitB {}
struct MyType {}
impl TraitAB for MyType {
fn as_a(&self) -> Rc<dyn TraitA> {Rc::clone(self)}
fn as_b(&self) -> Rc<dyn TraitB> {Rc::clone(self)}
}
impl TraitA for MyType {}
impl TraitB for MyType {}
fn main() {
let a: Rc<dyn TraitA>;
let b: Rc<dyn TraitB>;
{
let mut ab: Rc<dyn TraitAB> = Rc::new(MyType{});
a = ab.as_a();
b = ab.as_b();
}
}
This doesn't work though. According to the error messages:
xx | fn as_a(&self) -> Rc<dyn TraitA> {Rc::clone(self)}
| ^^^^ expected struct `std::rc::Rc`, found struct `MyType`
|
= note: expected type `&std::rc::Rc<dyn TraitA>`
found type `&MyType`
methods as_a
and as_b
can't know self is actually an Rc pointer.
Is there a way to do the cast of a cloned shared pointer?
Thanks
You need to implement
TraitAB
onRC<MyType>
Here is the code :
Btw i don't see any reason for
TraitAB
to extendTraitA + TraitB
but you can extend and implementTraitA
andTraitB
forRc<MyType>
as well.You can find working example with the implemented functions for
TraitA
andTraitB
in here : PlaygroundActually, that's not true! There's a rarely used feature that allows
self
to be taken as various standard kinds of references (Rc<Self>
,Box<Self>
, etc.).That means that you can rewrite your
TraitAB
asUnfortunately, as written,
as_a
andas_b
moveself: Rc<Self>
, sinceRc<T>
doesn't implementCopy
(onlyClone
). One way to fix this is to simply cloneab
before passing it into these methods. This also means that you don't need to clone theself
inside the method. (playground link)Using the nightly-only feature
arbitrary_self_types
, it's possible to makeas_a
andas_b
take self as&Rc<Self>
(which looks weird to me since it's a reference to a reference). This allowsab.as_a()
to be called without movingab
. The only problem with this approach is thatTraitAB
is no longer object-safe1, soRc<dyn TraitAB>
no longer works. (playground link).