Ante: A New Way to Blend Borrow Checking and Reference Counting
Languages ∩ Architecture
RSS<br>Github<br>r/Vale<br>Twitter<br>Discord
Ante: A New Way to Blend Borrow Checking and Reference Counting
Blending borrowing and reference counting without the crashes!
June 28, 2026
Evan Ovadia
Ante has taken the first step towards something we all thought was impossible: blending reference counting and borrow checking without run-time crashes. 0
This is very promising, because it means that someday, we can more easily use each approach when it makes sense without risking crashes. If there was a language like that, I could prototype a game in a flexible way with reference-counting, and gradually migrate it to faster borrow-checked code. 1
No mainstream language has figured out how to combine them seamlessly, even though many have tried.
Rust tried, but when we try to use Rust's reference-counting Rc type, it often requires RefCell (like Rc>) which can crash at run-time if you hold it wrong. 2 3 I wish rustc could check for proper Rc usage at compile-time! 4 5
Swift too has tried, with its new borrowing system, but it has an expensive run-time check which crashes at run-time if you hold it wrong.
It turns out, blending reference counting and borrow checking is hard, for reasons you'll see below.
So let's talk about Ante!
Ante is a work-in-progress! Some parts of this are implemented, some are still theoretical, and the design is still in flux. This is being actively developed as we speak, so follow Ante's progress on its site and discord!
Side Notes
(interesting tangential thoughts)
Notes [–]<br>Notes [+]
To be more specific, Ante has found a way to blend reference counting and borrow checking for mutable objects, without run-time panics or overhead that come from Rust's RefCell or Swift's exclusivity checking.
This is close to the same reason I work on Vale! But Vale uses generational references, which often risk these exact kinds of program halts.
For example, two people getting unique (read-write) references to it at the same time would crash it.
It also has try_borrow() and try_borrow_mut() methods which don't panic, but just moves the problem somewhere else.
And alas, GhostCell / QCell doesn't count, they bring in other limitations and aren't a drop-in replacement for RefCell.
There is Cell, but it doesn't let you get references to its innards. For example you can’t go from &Cell to a &Cell. Rust also tends to have a lot of friction when internal mutability is used in general, leading to many users avoiding it.
Ante
Ante aims to be a simpler Rust, a systems programming language with memory-safety and thread-safety. It has single ownership and borrow checking, so values are inline (on the stack, or in the containing struct/array).
And when the user wants to prioritize simplicity, they can opt into reference counting with the shared keyword on their types.
For example, this snippet would balance a red-black tree:
ante
// Color can be either an R or a B<br>shared type Color = | R | B
// RbTree can either be an Empty or a Tree<br>shared type RbTree t =<br>| Empty<br>| Tree Color (RbTree t) t (RbTree t)
// A balance function, for RbTree of any element type t<br>balance (tree: RbTree t) {Copy t}: RbTree t =<br>match tree<br>| Tree B (Tree R (Tree R a x b) y c) z d<br>| Tree B (Tree R a x (Tree R b y c)) z d<br>| Tree B a x (Tree R (Tree R b y c) z d)<br>| Tree B a x (Tree R b y (Tree R c z d)) -> Tree R (Tree B a x b) y (Tree B c z d)<br>| other -> other
I normally favor C-style syntax, but even I have to admit, this is beautiful. And it's concise too, as small as the Python equivalent, and smaller than the C++ equivalent and Rust equivalent.
But the most interesting thing for me is what Ante is doing in memory safety. Ante has shared mutability superpowers: if you want to mutably borrow reference-counted data, you don't need to risk run-time errors. No mainstream language can do that, not even Rust or Swift.
Before I talk about its shared mutability superpowers, let's start basic. Let's see how it does borrow checking, and then we'll add reference counting into the mix.
Shape-Stability
Ante has a concept of shape-stability , which means "a reference to something of stable shape is always valid 6 no matter what mutations are made elsewhere."
Because of this, Ante code can safely have multiple mutable borrow references to the same struct at the same time.
To set the stage, here's a heal function taking two mutable references to Entitys:
ante
type Entity =<br>energy: I32<br>health: I32
heal (healer: mut Entity) (target: mut Entity) =<br>healer.energy := healer.energy - 10<br>target.health := target.health + 10
In Ante, we can call heal with the same Entity for both parameters — for example, when an entity heals itself:
ante
self_heal (entity: mut Entity) =<br>heal entity entity
Mutating healer can't invalidate shared references to the Entity in any way, 7 so the compiler accepts this code as valid.
In other words, even though healer...