1

I am trying to implement depth first search on a graph.

#[derive(Debug)]
struct Interval {
    low: f64,
    high: f64,
    size: f64,
    left: Option<Box<Interval>>,
    right: Option<Box<Interval>>,
}

impl Interval {
    pub fn new(low: f64, high: f64) -> Self {
        Interval {
            low,
            high,
            left: None,
            right: None,
            size: high - low,
        }
    }

    pub fn expand(&mut self) {
        self.left = Option::Some(Box::new(Interval::new(self.low, self.low + self.size / 2.)));

        self.right = Option::Some(Box::new(Interval::new(
            self.low + self.size / 2.,
            self.high,
        )));
    }
}

The logic is to have a pointer to current node, then expand it, update the pointer to the left child of the expanded node, and proceed while the node under pointer satisfies some condition. However, I am failing to do this properly using the borrowed references logic. My current best attempt is:

fn main() {
    let mut current_node: &mut Interval = &mut Interval::new(1., 2.);

    while current_node.left.expect("PANIC").size > 0.01 {
        current_node.expand();
        current_node = &mut current_node.left.expect("PANIC");
    }

    println!("Deep down: {:?}", current_node);
}

Resulting error:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:34:11
   |
34 |     while current_node.left.expect("PANIC").size > 0.01 {
   |           ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:36:29
   |
36 |         current_node = &mut current_node.left.expect("PANIC");
   |                             ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:36:29
   |
34 |     while current_node.left.expect("PANIC").size > 0.01 {
   |           ----------------- borrow later used here
35 |         current_node.expand();
36 |         current_node = &mut current_node.left.expect("PANIC");
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
   |                             |
   |                             creates a temporary which is freed while still in use
   |
   = note: consider using a `let` binding to create a longer lived value

How to change the object I am referring to, while still being able to evaluate expressions on it and access its fields?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ikamen
  • 3,175
  • 1
  • 25
  • 47

1 Answers1

1

The following changes to main should work:

fn main() {
    let mut current_node: &mut Interval = &mut Interval::new(1., 2.);

    while current_node.left.as_ref().expect("PANIC").size > 0.01 {
        current_node.expand();
        current_node = current_node.left.as_mut().expect("PANIC");
    }

    println!("Deep down: {:?}", current_node);
}

expect takes self by value, so it tries to consume current_node.left which you are trying to use later, Option::as_ref() returns a new Option referencing the value of the original Option, which can then be consumed without messing with the original value. The same logic applies to adding as_mut to the second call, except for the mutability difference.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Luke B.
  • 1,258
  • 1
  • 17
  • 28