2

I created a type Space that has an optional fields lef_neighbor and right_neighbor of the same type Space. Rust needs to know the size of the type at compile time so I wrapped the types in a Box<>. I now want to create a method that I can call on a Space that creates the right_neighbor of this Space object and assigns it as such. It also needs to set the left_neighbor field of the new Space to the old Space so they can both find each other.

pub struct Space {
    left_neighbor: Option<Box<Space>>,
    right_neighbor: Option<Box<Space>>,
}

impl Space {
    pub fn new() -> Self {
        Self {
            left_neighbor: None,
            right_neighbor: None,
        }
    }

    pub fn create_neigbor(&mut self) {
        let neighbor_space = Space::new();
        neighbor_space.left_neighbor = Some(Box::new(self));
        self.right_neighbor = Some(Box::new(neighbor_space));
    }
}

(Playground link)

This gives the compile error:

   |
16 |         neighbor_space.left_neighbor = Some(Box::new(self));
   |                                                      ^^^^ expected struct `Space`, found `&mut Space`

How do I fix this problem?

avs
  • 617
  • 5
  • 13
  • 1
    Does this answer your question? [How do I express mutually recursive data structures in safe Rust?](https://stackoverflow.com/questions/36167160/how-do-i-express-mutually-recursive-data-structures-in-safe-rust) – E_net4 Oct 11 '21 at 11:36
  • `Box` is a smart pointer that points to a heap-allocated `Space` and *owns* it (i.e. drops it when the `Box` is dropped). You are trying to create a `Box` using a reference to `Space`, which is a different thing. Rust has no GC, so an object and a reference to an object are very different thing because the former is owned, while the latter is just borrowed. – user4815162342 Oct 11 '21 at 12:10

1 Answers1

2

First of all, what you are making is similar to a Doubly Linked List. Doubly Linked Lists are notoriously hard to do in safe rust. I recommend giving a read to Learning Rust with Entirely Too Many Linked Lists.

As a TLDR, you can use either raw pointers and unsafe, or store your spaces in an external storage (a vector, or something) and use indices into that space as a proxy to the actual thing, or use Rc/Arc instead of Box (though this will be probably lead to memory leaks, unless you properly use weak refs and such).

Kushagra Gupta
  • 514
  • 2
  • 13