Valen's Memory Safety: A New Kind of Borrow Checking
Valen's Memory Safety: A New Kind of Borrow Checking
By Evan Ovadia | October 11, 2026
Welcome to a deep dive into Valen's innovative and flexible approach to borrow checking. For those who don't know me, I have a passion for experimenting with memory safety paradigms—specifically, blending them in unconventional ways.
My ultimate goal is to discover the "holy grail" of memory safety: a system that possesses the raw power of Rust's borrow checker but maintains the intuitive simplicity and flexibility found in garbage collection (GC) or reference counting (RC).
To reach this goal, I believe we must conquer three specific hurdles:
- Challenge 1: Develop a more permissive borrow checker.
- Challenge 2: (To be discussed)
- Challenge 3: Integrate these two distinct systems into a cohesive whole.
This article focuses primarily on the first milestone: Valen's relaxed borrow checker. I will detail its capabilities, its inner workings, and its unique design.
⚠️ A Note on Syntax
For the sake of readability, I am using some "syntactic sugar" in the examples below. Please note that the following features are slated for a November release:
auto-deref- Direct struct indexing (e.g.,
my_vec[0]) - Group-based type inference (e.g.,
entity in world.entities[])
Despite these shorthand adjustments, the underlying borrow checker logic is fully functional as described.
The "Secret Sauce" of Valen
As we progress, I'll touch upon some unique architectural choices, such as:
- Rust Interop: How the borrow checker is designed specifically to allow Valen code to call Rust functions.
- Unified References: Unlike many other borrow checkers that utilize two distinct types of references, Valen employs only one.
(Note: This is a comprehensive post. If you are in a hurry, feel free to skip the backstory section below!)
Group Borrowing: From Near-Death to Industry Influence
Valen's foundation is built upon a concept called "Group Borrowing," originally conceived by Nick Smith. The fundamental premise is that the compiler tracks exactly where a reference points, using that spatial awareness to ensure memory safety.
The journey of Group Borrowing was not easy. It was originally intended for Mojo, but the proposal failed to gain traction with leadership at the time. For a while, it seemed the idea was dead. However, believing in its potential, we spent months refining the concept and published a detailed post last year to encourage other language designers to adopt it.
The response was overwhelming. The influence of Group Borrowing has spread across several modern languages:
The Fundamental Conflict
Most of these languages are trying to solve the same problem: flexibility. Valen needs to coexist with generational references and RC, while Carbon needs to remain compatible with C++.
The tension arises from a clash of philosophies:
| Approach | Core Restriction | Philosophy |
|---|---|---|
| Traditional Borrow Checking | If you have a reference, no one else can modify the object. | |
| RC / GC / C++ | Multiple entities can hold references while the object is modified. |
At first glance, these seem irreconcilable. However, Group Borrowing resolves this by shifting the requirement from "shared-xor-mutable" to a simpler rule: "no use-after-free."
Capabilities of Group Borrowing
Group borrowing provides memory safety with zero runtime overhead. It identifies use-after-free errors during compilation but is far less restrictive than previous methods.
Example 1: Catching an Error
The compiler can detect when a reference is used after the underlying data has been invalidated:
struct Entity {
hp int;
}
struct World {
entities Vec Entity;
}
func main() int {
let world = World(Vec Entity.new());
// ... some logic ...
// Compile error: Used a borrow after invalidated return first_ref
}
Example 2: Permissive Mutation
Conversely, the compiler recognizes patterns that typically trip up traditional borrow checkers. For instance, having multiple references to the same object and mutating through both is perfectly acceptable:
func main() int {
let list = Vec int.new();
let ref_a = list; // First reference
let ref_b = list; // Second reference
ref_a.push(73); // Mutate via ref_a
// ref_b is still valid here!
return 42;
}
Advanced Patterns Supported by Valen
Because of this relaxed approach, Valen supports several high-level patterns that are common in C++ but difficult in other memory-safe languages:
- Aliased Local Mutation: Multiple local variables pointing to one object, with write access granted to any of them.
- Nested Referencing: Passing a reference to an object and a reference to a field inside that same object, allowing mutation of the interior field.
- Multi-Parameter Mutation: Multiple function arguments pointing to the same object, all capable of performing writes.
- The ScopeGuard Pattern: Creating "rollback" structs that modify an object automatically when they go out of scope.
- Shared Subsystems: Multiple distinct structs holding mutable references to a single, common subsystem.
These are the patterns developers love from C++, and Valen is finally figuring out how to make them safe.