error[E0716]: temporary value dropped while borrowed

My code is like this.

// Definition for a binary tree node.
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
  pub val: i32,
   pub left: Option<Rc<RefCell<TreeNode>>>,
   pub right: Option<Rc<RefCell<TreeNode>>>,
}
//
impl TreeNode {
   #[inline]
   pub fn new(val: i32) -> Self {
         TreeNode {
          val,
           left: None,
           right: None
         }
    }
}
use std::rc::Rc;
use std::cell::RefCell;

struct Solution;

impl Solution {
    pub fn is_same_tree(p: Option<Rc<RefCell<TreeNode>>>, q: Option<Rc<RefCell<TreeNode>>>) -> bool {

        if p.is_none() || q.is_none() {
            return p == q;
        }

        /*let p_node = p.unwrap().clone();
        let q_node = q.unwrap().clone();
        unsafe {
            if (*p_node.as_ptr()).val == (*q_node.as_ptr()).val {
                return Self::is_same_tree((*p_node.as_ptr()).left.clone(),(*q_node.as_ptr()).left.clone()) && Self::is_same_tree((*p_node.as_ptr()).right.clone(),(*q_node.as_ptr()).right.clone());
            } else {
                return false;
            }
        }*/
        let n1 = p.clone().unwrap().borrow();
        let n2 = q.clone().unwrap().borrow();

        if n1.val == n2.val {
            return Self::is_same_tree(n1.left.clone(), n2.left.clone()) && Self::is_same_tree(n1.right.clone(), n2.right.clone());
        } else {
            return false;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_max() {
        let ans = Solution::is_same_tree(None, None);
        assert_eq!(ans, true);
    }
}

I can not understand why , I need to borrow it to get the val compared. And I don't want to use unsafe block.

The problem is that p.clone().unwrap() creates a new copy of the Rc<RefCell<TreeNode>>. Then, borrow has the signature (&'a RefCell<T>) -> Ref<'a, T>, so it operates on a borrow &Rc<RefCell<TreeNode>> of that cloned Rc. (An intermediate &Rc<RefCell<…>> to &RefCell<…> dereferencing step is also involved.)

But the temporary Rc<RefCell<TreeNode>> from the p.clone().unwrap() call is dropped at the end of the expression, making the Ref containing a lifetime of a borrow of that temporary unusable.

The straightforward solution to a dropped temporary value is to split up the expression and assign the temporary to a variable. I.e.

let this_was_a_temporary = p.clone().unwrap();
let n1 = this_was_a_temporary.borrow();

This solves your problem, however one has got to wonder why you’re cloning the Rc in the first place. The .unwrap() call without a clone has the same problem of involving a temporary, but you don’t actually need an owned copy of the Rc here at all; try Option::as_ref which can turn &Option<Rc<…>> into Option<&Rc<…>>, so that unwrapping just gives a reference to the original Rc which already has a location it lives in, so there’s no problematic temporary that will be dropped:

let n1 = p.as_ref().unwrap().borrow();
1 Like

In order to avoid unnecessary clones of the Rcs, you could go further and make the function arguments a reference, i.e. &Option<Rc<RefCell<TreeNode>>>.

impl Solution {
    pub fn is_same_tree(p: &Option<Rc<RefCell<TreeNode>>>, q: &Option<Rc<RefCell<TreeNode>>>) -> bool {

        if p.is_none() || q.is_none() {
            return p == q;
        }
        
        let n1 = p.as_ref().unwrap().borrow();
        let n2 = q.as_ref().unwrap().borrow();

        if n1.val == n2.val {
            return Self::is_same_tree(&n1.left, &n2.left) && Self::is_same_tree(&n1.right, &n2.right);
        } else {
            return false;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_max() {
        let ans = Solution::is_same_tree(&None, &None);
        assert_eq!(ans, true);
    }
}

furthermore, you’re basically just re-implementing (parts of) the derived Eq implementation here, you could just do

impl Solution {
    pub fn is_same_tree(p: &Option<Rc<RefCell<TreeNode>>>, q: &Option<Rc<RefCell<TreeNode>>>) -> bool {
        p == q
    }
}
1 Like

You are the rust master! I learned a lot, thanks very much!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.