
Heads up: this post exists because of ForrestKnight's video on coders learning the borrow checker. I had been splitting my systems work between Go and Zig; his framing is what finally pushed me to commit to Rust as the back-half of my React stack. The walk-through below is my own way of holding both memory models in my head — credit for the nudge goes to him.
Most "Rust vs garbage-collected language" debates argue about syntax, or about whether the borrow checker is "worth the fight." The cleaner way to see the difference is to watch the memory itself — where the value lives, when it dies, and *who decides*. So here's a side-by-side. Step through each line and watch how the two strategies diverge from the same starting point: a value on the heap.Two correct answers, two currencies
Both approaches are correct, but they pay for correctness in different currencies.
Rust pays at compile time. The borrow checker reads your code, proves that every reference is valid for as long as it's used, and emits the deallocation at the exact point the owner leaves scope. No runtime, no pauses, no late cleanup. The cost is that some programs that would be correct at runtime won't compile — you have to restructure them to satisfy the proof.
A tracing GC pays at runtime. Aliasing is free, the language doesn't care which reference "owns" what, and the collector handles cleanup whenever it decides to — usually triggered by allocation pressure. The cost is unpredictable pause times and a memory ceiling that lives above your actual working set.
When each shines
- Rust fits well when you control the deploy, want predictable latency, and don't mind designing data structures around ownership. Game engines, embedded, command-line tools, network services where p99 matters more than developer velocity.
- GC languages fit well when objects move fast and ownership genuinely changes hands often, when the application is short-lived per request (most web backends), or when you want to ship features and let the runtime handle bookkeeping.
The "borrow checker is fighting me" frustration usually comes from trying to write GC-shaped code in Rust. Once you stop reaching for shared mutable graphs and start modeling ownership as a tree, the checker mostly gets out of the way — and the bug it's trying to prevent really would have bitten you in the GC version too, just later and quieter.
Comments (0)
No comments yet. Be the first to share your thoughts!