Garbage collection for Rust: The finalizer frontier
Rust’s Design Goals vs. Garbage Collection
- Some argue GC “defeats the point” of Rust, whose core value is memory safety without a runtime GC via ownership and borrow checking.
- Others counter that Rust’s benefits go far beyond “no GC” (enums, traits, borrow checking, tooling, startup time, ecosystem), so an optional GC doesn’t undermine its identity.
- Several worry that if a GC library becomes the “easy” option, it could spread through dependencies and erode Rust’s low-level niche.
Intended Use Cases for GC in Rust
- Implementing language runtimes (JS engines, VMs) and complex object graphs with shared/cyclic references are cited as prime candidates.
- For most Rust code, library-level GC would be too awkward to use pervasively and is seen as a specialized tool, similar to
Rc/Arc. - Some suggest GC specifically for non‑critical business logic, keeping performance‑sensitive or embedded parts using standard Rust ownership.
Conservative vs Precise GC and Rust Semantics
- The discussed system (Alloy) is conservative because Rust allows pointers to be turned into integers and back (including in safe code via
usizeand in unsafe code via casts). - Critics note conservative GCs can’t move objects, limiting compaction and modern GC optimizations. They’re viewed as “stuck behind the frontier.”
- There’s debate over future pointer provenance rules: strict provenance might help precise GC, but today integer–pointer roundtrips and even exotic schemes (e.g. XORing pointers) mean a conservative GC can theoretically miss live objects or leak memory.
Finalizers, Resurrection, and Safety
- Finalizers are described as attractive but fundamentally fraught; mainstream GC languages advise avoiding them except in rare, expert cases.
- An example is given of object resurrection in a finalizer to handle locking, illustrating how subtle and error-prone finalization logic can be.
Async/Await, Leaks, and Desire for GC
- Some see Rust’s async/await model as a strong argument for GC (or even a “separate async Rust”), citing borrow-checker pain and lifetime issues across async boundaries.
- Others respond that active futures or careful use of
Arc/borrows might suffice, though safe Rust currently can’t express all desired scoped-task patterns.
Alternatives and Ecosystem Comparisons
- Alternatives raised: arenas, handle-based structures,
Rc/Arc, GhostCell, and reference counting (Swift-style). Arenas are seen as powerful but somewhat clumsy in Rust today. - Some suggest just using Go, Java, C#, OCaml, or Scala if you want GC + strong types, but others say Rust uniquely combines its type system, performance model, and tooling.