It ended up being quite large, but here's what happens in graphical form.
let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
Rc (a)
+-----+
| ptr |
+-----+
|
v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
|
(call this `TempRcContent`) v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Nil | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
Rc (b)
+-----+
| ptr |
+-----+
|
v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
|
Rc (a) |
+-----+ |
| ptr | |
+-----+ |
| |
v (strong count increased) v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 2 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
|
(call this `TempRcContent`) v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Nil | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::clone(&b);
}
Rc (b)
+-----+
| ptr |
+-----+
|
v (strong count increased)
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 2 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
^
Rc (a) (these point at each other now) |
+-----+ |
| ptr | |
+-----+ |
| |
v v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 2 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
(TmpRcContent counts dropped to 0, will drop List and deallocate)
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 0 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Nil | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
The unnamed Rc that was originally in a drops because it got overwritten, and this is what decreases the strong count in TmpRcContent to 0, ultimately resulting in it going away as expected.
// b drops (goes out of scope)
(strong count decreased)
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
^
Rc (a) (these point at each other still) |
+-----+ |
| ptr | |
+-----+ |
| |
v v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 2 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
The strong count pointed to by a remains 2 -- there are still two Rcs pointing at the contents, a and the Rc in what was originally pointed to by b.
// a drops (goes out of scope)
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
^
(these point at each other still) |
|
(strong count decreased) v
+----------+------------+-------------------------------------------------+
| weak = 0 | strong = 1 | List |
| | | +---------+-----------------------------------+ |
| | | | discrim | List::Cons | |
| | | | | +-----------+-------------------+ | |
| | | | | | value = 5 | RefCell<Rc> (tmp) | | |
| | | | | | | +---------+ | | |
| | | | | | | | +-----+ | | | |
| | | | | | | | | ptr | | | | |
| | | | | | | | +-----+ | | | |
| | | | | | | +---------+ | | |
| | | | | +-----------+-------------------+ | |
| | | +---------+-----------------------------------+ |
+----------+------------+-------------------------------------------------+
The strong counts of both instances remain one -- there is still an Rc pointing at each one (they are pointing at each other).
There's nothing else to drop by going out of scope after this, and no way to overwrite the Rcs to cause a drop, etc. So those two Rc allocations remain on the heap pointing at each other (they are leaked). They never tried to drop their Lists as their strong counts never reached 0.