1

I have a rust-playground link here, and the full code for my basic example is:

trait Obj {
    fn hit(&self, t0: f64, t1: f64) -> bool;
}

struct Leaf {
    data: f64,
}

impl Obj for Leaf {
    fn hit(&self, t0: f64, t1: f64) -> bool { return t0 < self.data && self.data < t1 }
}

struct Node<'a> {
    data: f64,
    left: &'a Box<dyn Obj>,
    right: &'a Box<dyn Obj>,
}

impl<'a> Obj for Node<'a> {
    fn hit(&self, t0: f64, t1: f64) -> bool {
        self.left.hit(t0, t1) || self.right.hit(t0, t1)
    }
}

impl<'a> Node<'a> {
    fn new(tmin: f64, tmax: f64) -> Self {
        let mid = (tmin + tmax) / 2.;
        if tmax - tmin < 1. {
            return Self { data: tmin, left: &Box::new(Leaf {data: tmin }), right: &Box::new(Leaf {data :tmax} ) };
        }
        let left = Node::new(tmin, mid);
        let right = Node::new(mid, tmax);
        Self {data: tmin, left: &Box::new(left), right: &Box::new(right) }
    }
}

fn main() {
    let node = Node::new(0., 100.);
    ()
}

It's a contrived example, but it gives the same compiler errors I get in my real version. In the constructor for Node, I get the following errors:

error[E0308]: mismatched types
  --> src/main.rs:29:83
   |
29 |             return Self { data: tmin, left: &Box::new(Leaf {data: tmin }), right: &Box::new(Leaf {data :tmax} ) };
   |                                                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Obj`, found struct `Leaf`
   |
   = note: expected reference `&'a std::boxed::Box<(dyn Obj + 'static)>`
              found reference `&std::boxed::Box<Leaf>`

error[E0308]: mismatched types
  --> src/main.rs:33:33
   |
33 |         Self {data: tmin, left: &Box::new(left), right: &Box::new(right) }
   |                                 ^^^^^^^^^^^^^^^ expected trait object `dyn Obj`, found struct `Node`
   |
   = note: expected reference `&'a std::boxed::Box<(dyn Obj + 'static)>`
              found reference `&std::boxed::Box<Node<'_>>`

Why do I get these errors? Both Leaf and Node implement Obj, and my understanding is that they could both be of type dyn Obj. I think it has something to do with lifetimes, but I can't think of how to fix this. What's the proper way of making this binary tree structure in Rust?

Calvin Godfrey
  • 2,171
  • 1
  • 11
  • 27
  • Just last week I implemented a binary tree as an exercise in Rust. Maybe it's useful: https://gist.github.com/jesperdj/466ff014adce89a1405ce033ff92231a – Jesper Jul 10 '20 at 12:51
  • 2
    `&Box` is pretty pointless. See https://stackoverflow.com/questions/40006219/why-is-it-discouraged-to-accept-a-reference-to-a-string-string-vec-vec-o – mcarton Jul 10 '20 at 12:51

1 Answers1

3

Box<..> is an owned type, so it can live on its own, been moved without a lifetime track. In your example you simply can remove all of the references and a lifetime, so the struct definition becomes:

struct Node {
    data: f64,
    left: Box<dyn Obj>,
    right: Box<dyn Obj>,
}

Here a full example.

Kitsu
  • 3,166
  • 14
  • 28