Why rust cannot infer the correct lifetime?

such program could successfully compiled since I force drop x1 before return.

#[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 merge_trees(t1: Option<Rc<RefCell<TreeNode>>>, t2: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
        match [t1,t2]{
            [Some(b1),Some(b2)]=>{
                let mut x2=b2.borrow_mut();
                let mut x1=b1.borrow_mut();
                x1.val+=x2.val;
                let t=x1.left.take();
                x1.left=Self::merge_trees(t,x2.left.take());
                let t=x1.right.take();
                x1.right=Self::merge_trees(t,x2.right.take());
drop(x1);//to ensure the lifetime of x1 is end.
                Some(b1)
            },
            [a,None]|[None,a]=>a
        }
        
    }
}
fn main(){
    let a=Some(Rc::new(RefCell::new(TreeNode{val:1,left:None,right:None})));
    let b=Some(Rc::new(RefCell::new(TreeNode{val:1,left:None,right:None})));
    dbg!(Solution::merge_trees(a,b));
}

if I delete the drop function, an error will occur:

error[E0505]: cannot move out of `b1` because it is borrowed
  --> src/main.rs:31:22
   |
25 |                 let mut x1=b1.borrow_mut();
   |                            -- borrow of `b1` occurs here
...
31 |                 Some(b1)
   |                      ^^ move out of `b1` occurs here
32 |             },
   |             - borrow might be used here, when `x1` is dropped and runs the destructor for type `std::cell::RefMut<'_, TreeNode>`

why Rust cannot auto-drop x1?

I just tried it and it worked. I did have to guess the definition of TreeNode though. Here is the full code:

use std::rc::Rc;
use std::cell::RefCell;

struct Solution;
#[derive(Debug)]
struct TreeNode {
    val: u8,
    left: Option<Rc<RefCell<TreeNode>>>,
    right: Option<Rc<RefCell<TreeNode>>>,
}

impl Solution {
    pub fn merge_trees(t1: Option<Rc<RefCell<TreeNode>>>, t2: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
        match [t1,t2]{
            [Some(b1),Some(b2)]=>{
                let mut x2=b2.borrow_mut();
                let mut x1=b1.borrow_mut();
                x1.val+=x2.val;
                let t=x1.left.take();
                x1.left=Self::merge_trees(t,x2.left.take());
                let t=x1.right.take();
                x1.right=Self::merge_trees(t,x2.right.take());
drop(x1);//to ensure the lifetime of x1 is end.
                Some(b1)
            },
            [a,None]|[None,a]=>a
        }
        
    }
}
fn main(){
    let a=Some(Rc::new(RefCell::new(TreeNode{val:1,left:None,right:None})));
    let b=Some(Rc::new(RefCell::new(TreeNode{val:1,left:None,right:None})));
    dbg!(Solution::merge_trees(a,b));
}

Thanks for your reply.
and sorry for my lately reply... I forgot to login into this forum.

I wrote the drop sentences manually and uncheck, thus I have losing a ; after drop
...but that is not the problem.

my problem is that, Rust cannot auto drop x1 and generate an error when I delete the whole drop function.

I know how to solve it, I just want to know why..

Values are automatically dropped at the end of the scope after the tail expression is evaluated. This means that x1 is dropped after Some(b1) has been constructed.

Rust will never drop a variable early, because that could change the meaning of your code, which would be terrible.

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.