A BorrowMutError report when use a different Argument

⚓ Rust    📅 2025-08-27    👤 surdeus    👁️ 4      

surdeus

I wrote a Double-end linked list, "already borrowed: BorrowMutError" Error reported when call the delete method with "&head.borrow().next.as_ref().unwrap() " but works ok with argument "&head".

I spent hours unable to figure out why is that ? Please help. thank you.

struct Node<T> {
    value: T,
    next: Option<Rc<RefCell<Node<T>>>>,
    prev: Option<Rc<RefCell<Node<T>>>>,
}

impl<T> Node<T> {
    fn new(value: T) -> Self {
        Self { value, next: None, prev: None }
    }
}

fn delete<T>(node: &Rc<RefCell<Node<T>>>) {
    let prev_node = node.borrow().prev.clone();
    let next_node = node.borrow().next.clone();
    node.borrow_mut().prev = None;
    node.borrow_mut().next = None;
    if let Some(ref prev) = prev_node{
// Error: already borrowed: BorrowMutError report here when 
// call the delete method with argument: &head.borrow().next.as_ref().unwrap() 
// but works ok with argument: &head
        prev.borrow_mut().next = next_node.clone();  
    }
    
    if let Some(next) = next_node {
        next.borrow_mut().prev = prev_node;
    }
}

fn insert_after<T>(node: &Rc<RefCell<Node<T>>>, value: T) {
    let new_node = Rc::new(RefCell::new(Node::new(value)));
    let next_node = node.borrow().next.clone();
    
    node.borrow_mut().next = Some(new_node.clone());
    new_node.borrow_mut().prev = Some(node.clone());
    
    if let Some(next) = next_node {
        new_node.borrow_mut().next = Some(next.clone());
        next.borrow_mut().prev = Some(new_node);
    }
}

fn insert_before<T>(node: &Rc<RefCell<Node<T>>>, value: T) {
    let new_node = Rc::new(RefCell::new(Node::new(value)));
    let prev_node = node.borrow().prev.clone();
    
    node.borrow_mut().prev = Some(new_node.clone());
    new_node.borrow_mut().next = Some(node.clone());
    
    if let Some(prev) = prev_node {
        new_node.borrow_mut().prev = Some(prev.clone());
        prev.borrow_mut().next = Some(new_node);
    }
}

fn traverse_forward<T: std::fmt::Debug>(start: &Rc<RefCell<Node<T>>>) {
    let mut current = Some(start.clone());
    while let Some(node) = current {
        print!("{:?} ", node.borrow().value);
        current = node.borrow().next.clone();
    }
    println!();
}

fn traverse_backward<T: std::fmt::Debug>(end: &Rc<RefCell<Node<T>>>) {
    let mut current = Some(end.clone());
    while let Some(node) = current {
        print!("{:?} ", node.borrow().value);
        current = node.borrow().prev.clone();
    }
    println!();
}

here is the unit test:

#[test]
fn test_create(){
    let head = Rc::new(RefCell::new(Node::new(1)));
    insert_after(&head, 2);
    insert_after(&head.borrow().next.as_ref().unwrap(), 3);
    insert_before(&head, 0);
    
    println!("Traverse forward:");
    traverse_forward(&head.borrow().prev.as_ref().unwrap().clone());
    
    let tail = head.borrow().next.as_ref().unwrap().borrow().next.as_ref().unwrap().clone();
    println!("Traverse backward:");
    traverse_backward(&tail);
    
    println!("After deleting node with value 2:");
    // call with '&head.borrow().next.as_ref().unwrap()' reports Error: already borrowed: BorrowMutError
    // call with "&head" works ok. 
    delete(&head.borrow().next.as_ref().unwrap());
    traverse_forward(&head.borrow().prev.as_ref().unwrap().clone());    
}

3 posts - 2 participants

Read full topic

🏷️ Rust_feed