pub struct Gc<T> { /* private fields */ }Expand description
A small, copyable, type-tagged handle to one object in a Heap.
A Gc<T> is how a garbage-collected object refers to another. It is eight bytes
— a slot index plus a generation stamp — so passing one is about as cheap as
passing a u64, and unlike a &T it carries no borrow. That is what lets the
runtime build cyclic object graphs: a node stores Gc<T> handles to its
neighbours, edges point in every direction, and the borrow checker never enters
the picture. Resolving a handle is a direct slot lookup through
Heap::get / get_mut.
The generation stamp is what makes a handle safe to hold across a collection. A
slot’s generation advances every time the slot is reclaimed and reused, so a
handle to an object that was collected no longer matches the object now living
in that slot: it resolves to None rather than silently aliasing an unrelated
value. A handle is therefore never a dangling pointer — at worst it is a stale
handle that reads as absent.
The T tag is compile-time only and occupies no space: it stops a Gc<Value>
from being resolved against a Heap<Node>. Gc<T> is Copy, Eq, Ord, and
Hash for every T — the tag never adds a bound — so it works as a map key
regardless of what it points at. There is no public constructor: a Gc can only
come from Heap::alloc / try_alloc.
§Examples
use gc_lang::{Heap, Trace, Tracer};
struct Node;
impl Trace for Node {
fn trace(&self, _: &mut Tracer<'_>) {}
}
let mut heap = Heap::new();
let handle = heap.alloc(Node);
// It is Copy and eight bytes wide, whatever it points at.
let also = handle;
assert_eq!(handle, also);
assert_eq!(core::mem::size_of_val(&handle), 8);