22
Building
push_front: allocate a node, link it to the old head in both directions, swing self.head. The shape is the same as the singly-linked stack but every field write goes through borrow_mut() on a RefCell, and every node pointer is cloned through Rc::clone.
- Build the new node, wrap it in
Rc::new(RefCell::new(...)), then patch up the old head'sprevpointer to point at the new node. The old head and the new node both hold anRcto each other — refcount 2 on each.pub fn push_front(&mut self, elem: T) { let new_head = Rc::new(RefCell::new(Node { elem, prev: None, next: None, })); match self.head.take() { Some(old_head) => { old_head.borrow_mut().prev = Some(new_head.clone()); new_head.borrow_mut().next = Some(old_head); self.head = Some(new_head); } None => { // empty list: head and tail both become the new node self.tail = Some(new_head.clone()); self.head = Some(new_head); } } } -
borrow_mut()returns aRefMut<T>guard. While the guard is alive, no other borrow of that RefCell can exist; anotherborrow()orborrow_mut()on the same cell will panic. The compiler does not know any of this — the check is at runtime, on every call.// fine: two separate cells let a = node_a.borrow_mut(); let b = node_b.borrow_mut(); // panic: same cell, two mut borrows let x = node.borrow_mut(); let y = node.borrow_mut(); // thread 'main' panicked at 'already borrowed: BorrowMutError' - The empty-list arm has to set both
headandtailto the same node, which means cloning theRc.Rc::clone(also spelled.clone()on anRc) bumps the refcount, doesn't deep-copy the node. TwoRchandles, one heap allocation.// after push_front on an empty list: // self.head -> Rc(count=2) -> Node{...} // self.tail -> Rc(count=2) -> (same Node)