0

Im trying to write a basic nary tree, where I have several traits that are all intended to work on structs which will form the nodes of the tree. These structs will have mutable references to the other nodes of the tree, so I have included lifetime parameters in my trait definitions.

For instance, this is the trait which all the structs will implement:

pub trait Node<'a>: NodeClone {

    fn value(&self) -> String;

    fn parent(&self) -> Option<Box<dyn Node>>;

    fn children(&self) -> Vec<Box<dyn Node>>;

    fn set_parent(&mut self, parent: &mut Box<dyn Node>);

    fn push_child(&mut self, child: &mut Box<dyn Node>);

    fn to_string(&self, current: &mut String) -> String;
}

Anything which implements Node must also implement NodeClone, which looks like:

pub trait NodeClone { 

    fn clone_box(&self) -> Box<dyn Node>;
}

impl<'a, T> NodeClone for T where T: 'static + Node<'a> + Clone, {

    fn clone_box(&self) -> Box<dyn Node> {

        return Box::new(self.clone());
    }
}

impl<'a> Clone for Box<dyn Node<'a>> {

    fn clone(&self) -> Box<dyn Node<'a>> {

        return self.clone_box();
    }
}

This is one of the structs which will form the tree:

#[derive(Clone)]
pub struct Operation<'a> {

    pub parent: Option<&'a mut Box<dyn Node<'a>>>,

    pub children: Vec<&'a mut Box<dyn Node<'a>>>
}

When I then try and implement Node for Operation like:

impl<'a> Node<'a> for Operation<'a> 

I get the error that:

error[E0477]: the type `Operation<'a>` does not fulfill the required lifetime
  --> src/language/components/node/operation.rs:31:10
   |
31 | impl<'a> Node<'a> for Operation<'a> {
   |          ^^^^^^^^
   |
note: type must satisfy the static lifetime as required by this binding
  --> src/language/components/node.rs:15:21
   |
15 | pub trait Node<'a>: NodeClone {
   | 

When I change the implementation of Operation to include a static lifetime:

impl<'a> Node<'a> for Operation<'static>

The fields of my struct Operation give me the error that:

the trait bound `&mut Box<(dyn Node<'_> + 'static)>: Clone` is not satisfied

Im not sure which lifetime I should change and where to solve this. Please help!

m.tracey
  • 173
  • 1
  • 10
  • Does this answer your question? [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) – Chayim Friedman Apr 06 '22 at 00:00
  • 2
    While this doesn't _directly_ address your question, even if you'll be able to solve this specific error you'll get many others. TL;DR: What you're trying to do (a self-referential struct) is impossible, at least in this way. – Chayim Friedman Apr 06 '22 at 00:01
  • Mutable reference is not Clone, so you can't derive Clone for Operation (both parent and children contain mut refs). – stepan Apr 06 '22 at 00:06
  • 1
    I think your best bet is to replace `&mut Box` with `Rc>` (or `Arc>` if multi-threaded). – BallpointBen Apr 06 '22 at 02:40
  • @BallpointBen do i need to include dyn for RefCell in the same way that you do for box? Do i understand correctly that a Box is similar to a C++ unique_ptr and a RefCell is similar to the shared_ptr? – m.tracey Apr 06 '22 at 02:50
  • 1
    @m.tracey you do still need `dyn` in order to use traits as types. Not sure about the correspondence to C++, but that sounds right -- `Box` has a single owner and is dropped when its scope ends, whereas `Rc` has multiple owners and is dropped only when all of its owners' scopes end. – BallpointBen Apr 06 '22 at 02:55
  • No, the equivalent of `std::shared_ptr` in Rust is `Rc` (or more precisely, `Arc`, because `std::shared_ptr` is atomic). `RefCell` has no C++ equivalent, as it allows interior mutability, and this concept doesn't really exist in C++ (the most similar thing, though not quite the same, is `mutable`). – Chayim Friedman Apr 06 '22 at 04:35

0 Answers0