A reference counted smart pointer is the same as a shared pointer in C++. The Rc<T> pointer keeps track of the number of references to it and frees up memory when the reference count is zero.
Rc<T> can only be used for single-threaded scenarios.
Only immutable borrow checking is done at compile time.
Rc<T> can only hold immutable data. Pair with RefCell<T> for mutability.
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
    let v = Rc::new(RefCell::new(vec![1, 2, 3]));
    let w = Rc::clone(&v);
    let x = Rc::clone(&v);
    // Add 4 to vector
    v.borrow_mut().push(4);
    //would_cause_panic(&v);
    println!("{:?}", x);
}
fn would_cause_panic(v: &Rc<RefCell<Vec<u32>>>) {
    let mut one_borrow = v.borrow_mut();
    // Panic because two mutable references
    // During rumtime with RefCell
    let mut two_borrow = v.borrow_mut();
}
When strong_count reaches 0, the instance is cleaned up. Clean up does not care how many weak references there are. Using Weak<T> is one way to help prevent memory leaks (via circular referencing).
Since what Weak<T> references may have been dropped, it is necessary to call upgrade which returns an Option<RC<T>> to verify that the reference still exists.
use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}
fn main() {
    let leaf = Rc::new(Node {
        value: 6,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![]),
    });
    println!("leaf parent = {:#?}", leaf.parent.borrow().upgrade()); // None
    let branch = Rc::new(Node {
        value: 42,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![Rc::clone(&leaf)]),
    });
    // Downgrade strong to weak
    *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
    println!("leaf parent = {:#?}", leaf.parent.borrow().upgrade()); // Some
}