Hello everyone. I have run into this problem a couple of times and was wondering if there is a nice pattern to solve it. I have a trait Trait
which I want to use only in an Rc
. I also want the implementations of the trait to be able to refer to their enclosing Rc
.
trait Trait {
fn thing(&self) -> Rc<Trait>;
}
struct TraitString(String);
impl Trait for TraitString {
fn thing(&self) -> Rc<Trait> {
// Return copy of enclosing Rc.
}
}
Obviously this example has a bunch of problems as it doesn't enforce that you are calling it on an Rc and the impl doesn't even know about the Rc. However I can't find a way to write it. I have come up with the following (unsatisfactory) solutions.
Use an enum and have all possible implementations inline.
This allows me to impl on Rc<Thing>
and then I can simply clone self to implement the method. However this requires me to centralize the implements and every method becomes an unsightly match
.
impl Thing for Rc
This allows me to access and clone the Rc but now I need to wrap my thing in another layer of indirection because Rust doesn't know that all impls will be for Rc. This means that Rc<Thing>
turns into Box<Rc<Thing>>
Make an impl trait with extra arguments
trait ThingImpl {
fn thing(&self, rc_self: Rc<Thing>) -> Rc<Thing>;
}
struct Thing(Rc<ThingImpl>);
impl Thing {
fn thing(&self) -> Rc<Thing> {
self.0.thing(self.clone())
}
}
This works but 1) requires this ugly wrapper. 2) Looses type-safety on the rc_self param. (You can do an unsafe cast because it will be the right type but that is ugly). This seems like the best solution however it requires a lot of unsafe and boilerplate code.
C++ has std::enable_shared_from_this
which solves this problem but I was wondering if there is a nice solution in Rust.