use std::cell::RefCell; use tracing_rc::rc::{ collect_full, Gc, GcVisitor, Trace, }; #[test] fn pure_gc_necromancy() { struct Zombie { cycle: Option>, dead: Option>, } impl Trace for Zombie { fn visit_children(&self, visitor: &mut GcVisitor) { self.cycle.visit_children(visitor); self.dead.visit_children(visitor); } } thread_local! { static ZOMBIE: RefCell>> = RefCell::new(None) }; #[derive(Debug)] struct Necro { gc: Option>, } impl Drop for Necro { fn drop(&mut self) { ZOMBIE.with(|zombie| { *zombie.borrow_mut() = Some(Gc::new(Zombie { cycle: None, dead: Some(self.gc.as_ref().unwrap().clone()), })); }) } } impl Trace for Necro { fn visit_children(&self, visitor: &mut GcVisitor) { visitor.visit_node(self.gc.as_ref().unwrap()); } } #[derive(Debug)] struct Mancer { gc: Gc, } impl Trace for Mancer { fn visit_children(&self, visitor: &mut GcVisitor) { visitor.visit_node(&self.gc); } } let necro = Gc::new(Necro { gc: None }); let mancer = Gc::new(Mancer { gc: necro.clone() }); necro.borrow_mut().gc = Some(mancer); drop(necro); collect_full(); let mut resurrected_owner = None; ZOMBIE.with(|zombie| { resurrected_owner = zombie.borrow().clone(); *zombie.borrow_mut() = None; }); resurrected_owner.as_ref().unwrap().borrow_mut().cycle = resurrected_owner.clone(); drop(resurrected_owner); collect_full(); }