Last active: a year ago
Rust RefCell and Rc stack overflow
use anyhow::Result;
use std::{cell::RefCell, rc::Rc};
#[derive(Debug)]
enum List {
Cons(i32, RefCell<Rc<List>>),
Nil,
}
impl List {
fn tail(&self) -> Option<&RefCell<Rc<List>>> {
match self {
List::Cons(_, item) => Some(item),
List::Nil => None,
}
}
}
fn main() -> Result<()> {
use List::*;
// Create a List call a, his tail is Nil
let a = Rc::new(Cons(1, RefCell::new(Rc::new(Nil))));
println!("a's strong count {}", Rc::strong_count(&a));
// Create a List call b, his tail is a
let b = Rc::new(Cons(2, RefCell::new(a.clone())));
println!(
"After b created, a's strong count is {}",
Rc::strong_count(&a)
);
// Because the RefCell, we can get a's tail, and point it to b
if let Some(link) = a.tail() {
*link.borrow_mut() = b.clone();
}
println!(
"After point a's tail to b, b's strong count is {}, And a's {}",
Rc::strong_count(&b),
Rc::strong_count(&a)
);
// And overflow
// println!("a's tail {:?}", a.tail());
Ok(())
}
use anyhow::Result;
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
#[derive(Debug)]
enum List {
Cons(i32, RefCell<Weak<List>>),
Nil,
}
impl List {
fn tail(&self) -> Option<&RefCell<Weak<List>>> {
match self {
List::Cons(_, item) => Some(item),
List::Nil => None,
}
}
}
fn main() -> Result<()> {
use List::*;
let nil = Rc::new(Nil);
// Create a List call a, his tail is Nil
let a = Rc::new(Cons(1, RefCell::new(Rc::downgrade(&nil))));
println!("a's strong count {}", Rc::strong_count(&a));
// Create a List call b, his tail is a
let b = Rc::new(Cons(2, RefCell::new(Rc::downgrade(&a))));
println!(
"After b created, a's strong count is {}",
Rc::strong_count(&a)
);
// Because the RefCell, we can get a's tail, and point it to b
if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::downgrade(&b);
}
println!(
"After point a's tail to b, b's strong count is {}, And a's {}",
Rc::strong_count(&b),
Rc::strong_count(&a)
);
// And overflow
println!("a's tail {:?}", a.tail());
Ok(())
}