1
use std::{cell::RefCell, rc::Rc};

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

fn find_min(mut node: &Option<Rc<RefCell<TreeNode>>>) -> i32 {
    while node.as_ref().unwrap().borrow().left.is_some() {
        node = &node.as_ref().unwrap().borrow().left;
    }
    node.as_ref().unwrap().borrow().val
}
error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:12:17
   |
10 | fn find_min(mut node: &Option<Rc<RefCell<TreeNode>>>) -> i32 {
   |                       - let's call the lifetime of this reference `'1`
11 |     while node.as_ref().unwrap().borrow().left.is_some() {
12 |         node = &node.as_ref().unwrap().borrow().left;
   |         --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------ temporary value is freed at the end of this statement
   |         |       |
   |         |       creates a temporary which is freed while still in use
   |         assignment requires that borrow lasts for `'1`

TreeNode is given and cannot be changed.

I understand why I get the error, but don't know how to fix it.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Evgeni Nabokov
  • 2,421
  • 2
  • 32
  • 36
  • It looks like your question might be answered by the answers of [How to resolve “creates a temporary variable which is freed while still in use”?](https://stackoverflow.com/q/64728534/155423); [Cyclic reference of RefCell borrows in traversal](https://stackoverflow.com/q/36597987/155423); [Borrowed RefCell does not last long enough when iterating over a list](https://stackoverflow.com/q/55331919/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Nov 11 '20 at 20:14
  • Thank you for the links. One of them provided the answer to my question. I added own solution. – Evgeni Nabokov Nov 12 '20 at 00:44

2 Answers2

0

UPDATE:

Using Rc as the argument looks better perhaps:

use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<TreeNode>>,
    pub right: Option<Rc<TreeNode>>,
}

pub fn find_min(mut current: Rc<TreeNode>) -> i32 {
    while current.left.is_some() {
        current = Rc::clone(current.left.as_ref().unwrap());
    }
    current.val
}

fn main() {
    let left_child = TreeNode {
        val: 1,
        left: None,
        right: None,
    };
    let root = TreeNode {
        val: 6,
        left: Some(Rc::new(left_child)),
        right: None,
    };
    println!("min: {}", find_min(Rc::new(root)));
}

The RefCell and the mut stuff look redundant to me?

What about:

use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<TreeNode>>,
    pub right: Option<Rc<TreeNode>>,
}

pub fn find_min(root: &TreeNode) -> i32 {
    let mut current = Rc::new(root);
    while current.left.is_some() {
        current = Rc::new(current.left.as_ref().unwrap());
    }
    current.val
}
Frederick Zhang
  • 3,593
  • 4
  • 32
  • 54
0

Wrote my solution based on this answer:

fn find_min(node: &Option<Rc<RefCell<TreeNode>>>) -> i32 {
    let mut curr = node.as_ref().unwrap().clone();
    while curr.borrow().left.is_some() {
        let tmp = curr.borrow().left.as_ref().unwrap().clone();
        curr = tmp;
    }
    let res = curr.borrow().val;
    res
}

Both temporary variables do not look good, but it is what it is.

Evgeni Nabokov
  • 2,421
  • 2
  • 32
  • 36