Valen's Memory Safety: A New Kind of Borrow Checking

本文为原文前 6,000 字符的节选翻译,完整内容请查看原文。

Valen’s Memory Safety: A New Kind of Borrow Checking

Languages ∩ Architecture Github RSS Bluesky Mastodon r/valen Discord Valen’s Memory Safety: A New Kind of Borrow Checking References that remember where they point to! Oct 11, 2026 — Evan Ovadia This post is about Valen’s new flexible borrow checker. Welcome! You all know me, I love exploring new memory safety approaches and blending them together in weird ways. It’s part of my eternal quest to find the memory safety holy grail: something as powerful as Rust’s borrow checking, yet something as simple and flexible as reference counting or garbage collection. 0 1 I’ve long suspected that to find the holy grail, we’d have to solve three memory-safety challenges: Can we make a more relaxed borrow checker? 2 Can we make a borrow checker read more complex data? 3 4 Can we make those two systems work together at the same time? Vague and arcane, I know! Further below I’ll explain what that all means, and how Valen might have found a solution for them. 5 This post mainly focuses on the first piece: Valen’s more relaxed borrow checker. So in this post, I’ll talk about what it is, what it can do, and how it works. In this article, I take some liberties with syntactic sugar for clarity: auto-deref, directly indexing a struct (my_vec[0]), and inferring types from groups (entity in world.entities[]) are coming in November. Aside from those syntactic adjustments, the borrow checker works for everything we talk about. 6 And, along the way, I’ll explain some of the weirder tidbits, like: How Valen’s borrow checker is shaped to let Valen code call Rust code. How a compiler can remember where a reference is pointing. How Valen has one kind of borrow reference, as opposed to the two that other borrow checkers have. Also, this article is gloriously long and has a lot of context, so I’ll let you know when to skip ahead. Let’s dive in!

Valen 的内存安全:一种新型借用检查。引用能够记住它们指向的位置!2026 年 10 月 11 日 — Evan Ovadia。这篇文章是关于 Valen 新的灵活借用检查器的。欢迎!你们都知道我,我喜欢探索新的内存安全方法,并以奇特的方式将它们融合在一起。这是我寻找内存安全圣杯的永恒追求的一部分:既要像 Rust 的借用检查那样强大,又要像引用计数或垃圾回收那样简单灵活。我一直怀疑,要找到圣杯,我们必须解决三个内存安全挑战:我们能制造一个更宽松的借用检查器吗?我们能制造一个能读取更复杂数据的借用检查器吗?我们能让这两个系统同时协同工作吗?我知道这很模糊且晦涩!在下文中,我将解释这一切意味着什么,以及 Valen 可能如何为它们找到了解决方案。这篇文章主要关注第一部分:Valen 更宽松的借用检查器。因此,在这篇文章中,我将讨论它是什么、它能做什么以及它是如何工作的。在本文中,为了清晰起见,我采用了一些语法糖:自动解引用、直接索引结构体 (my_vec[0]) 以及从组中推断类型 (entity in world.entities[]) 将在 11 月推出。除了这些语法调整外,借用检查器适用于我们讨论的所有内容。在此过程中,我将解释一些更奇怪的细节,例如:Valen 的借用检查器是如何塑造以允许 Valen 代码调用 Rust 代码的;编译器如何记住引用指向的位置;以及 Valen 如何拥有一种借用引用,而不是其他借用检查器所拥有的两种。此外,这篇文章非常长且包含大量背景信息,所以我会在需要跳过时通知你。让我们开始吧!

Group borrowing: a near miss, and huge potential (This is just backstory that I love telling, feel free to skip this section!) Valen’s approach is built on the “Group Borrowing” proposal which was designed by my friend Nick Smith. It’s built around the core concept that the compiler remembers where a reference points to, (I’ll explain this later) and it uses that information to check that programs are memory-safe. The design’s life had a rough start; it was almost buried in the flows of time. It was originally designed with Mojo in mind, but alas, despite my best efforts I couldn’t convince the higher-ups that we should use it. 7 Group borrowing was dead before it had the chance to succeed. But I knew it had massive potential, if it could just make it into the world somehow. So we spent months sharpening the explanation and figuring out its benefits, and wrote a post 8 on it last year, hoping other languages would pick it up. And they did! It spread far and wide. 9 Google’s Carbon language pivoted completely to group borrowing (and even credited our article, which was nice of them!) Ante started working it into their language, see Shared Mutability and Stability. Plecra’s exclusion typing is redesigning the Rust borrow checker with concepts from group borrowing and GhostCell. 10 Zeta blended group borrowing with disjointness 11 to factor run-time facts into compile-time memory safety. Fang is working it into their designs, see Cyclic References in Fang. And now, my Valen combines group borrowing with Vale’s 12 approach, and makes it interop with Rust code too. Most of these languages are circling the same sort of challenge: how to make a more flexible borrow checker. For example, Valen wants to make a borrow checker that’s flexible enough to work with reference counting and generational references, and Carbon wants to make a borrow checker flexible enough to work with C++ code. This is difficult, because there’s been a fundamental conflict between borrow checking and other approaches. It can be summed up like this: 13 Borrow checking has the “shared-xor-mutable” restriction: if you hold a reference to an object, nobody else can change the object. Other approaches want to allow holding a reference to an object while letting others change it. 14 15 You’re probably thinking, “There’s definitely no way to resolve this.” It does seem that way! But group borrowing actually resolves the conflict, by relaxing “shared-xor-mutable” to “no use-after-free”. That was cryptic and won’t make any sense, but it will later when I explain how group borrowing works. So let’s see what group borrowing can do, and then I’ll explain how it works.

组借用:一次险些错过的机会与巨大的潜力(这只是我喜欢讲述的背景故事,请随意跳过本节!)Valen 的方法建立在我的朋友 Nick Smith 设计的“组借用”提案之上。它围绕一个核心概念构建,即编译器记住引用指向的位置(我稍后会解释),并利用这些信息来检查程序是否内存安全。该设计的生命有一个艰难的开始;它几乎被淹没在时间的洪流中。它最初是为 Mojo 设计的,但遗憾的是,尽管我尽了最大努力,我还是没能说服高层使用它。组借用在有机会成功之前就夭折了。但我知道它有巨大的潜力,只要它能以某种方式进入这个世界。因此,我们花了几个月的时间来完善解释并找出其好处,并在去年写了一篇关于它的文章,希望其他语言能采用它。他们确实做到了!它传播得很广。Google 的 Carbon 语言完全转向了组借用(甚至引用了我们的文章,这很不错!)。Ante 开始将其整合到他们的语言中,参见“共享可变性和稳定性”。Plecra 的排他类型正在用组借用和 GhostCell 的概念重新设计 Rust 的借用检查器。Zeta 将组借用与不相交性相结合,将运行时事实纳入编译时内存安全。Fang 正在将其整合到他们的设计中,参见“Fang 中的循环引用”。现在,我的 Valen 将组借用与 Vale 的方法相结合,并使其也能与 Rust 代码互操作。大多数这些语言都在围绕同一种挑战:如何制造一个更灵活的借用检查器。例如,Valen 希望制造一个足够灵活的借用检查器,以配合引用计数和代际引用工作;而 Carbon 希望制造一个足够灵活的借用检查器,以配合 C++ 代码工作。这很困难,因为借用检查与其他方法之间存在根本冲突。可以总结如下:借用检查具有“共享或可变”(shared-xor-mutable)限制:如果你持有一个对象的引用,其他人就不能更改该对象。其他方法则希望允许在持有对象引用的同时,让其他人更改它。你可能在想:“绝对没有办法解决这个问题。”看起来确实如此!但组借用实际上通过将“共享或可变”放宽为“无释放后使用”(no use-after-free)来解决了这一冲突。这很隐晦,现在听起来毫无意义,但当我稍后解释组借用是如何工作时,你就会明白了。那么,让我们看看组借用能做什么,然后我再解释它是如何工作的。

What group borrowing can do Group borrowing gives a program memory safety without run-time cost. 16 It catches use-after-free problems at compile time, and it does it in a way that has less restrictions than previous approaches. Here’s an example where a use-after-free error is caught at compile time: valen struct Entity { hp int; } struct World { entities Vec; } func main() int { let world = World(Vec.new()); world.entities.push(Entity(42)); let first_ref = &world.entities[0]; world.entities = Vec.new(); // Compile error: Used a borrow after invalidated return first_ref.hp; } It’s an unusually flexible approach. Usually, compilers have trouble with the below program, but this approach understands that it’s safe: 17 valen func main() int { let list = Vec.new(); // Make two refs to the list let ref_a = &list; let ref_b = &list; // Mutate the list through both refs ref_a.push(42); ref_b.push(73); return 42; } Group borrowing accepts a lot of patterns that are normally hard for borrow checkers, such as: Having multiple local variables that point to the same object, and write through any of them (like above). Take a parameter pointing at an object, and another parameter pointing somewhere inside that object, and write through only the latter (we’ll see this in the next section). Having multiple function parameters that point to the same object, and write through any of them. 18 Make a “rollback” struct, that will change an object when

组借用能做什么:组借用为程序提供了内存安全,且没有运行时成本。它在编译时捕获“释放后使用”问题,并且其限制比以前的方法更少。这是一个在编译时捕获“释放后使用”错误的示例:[代码示例]。这是一种异常灵活的方法。通常,编译器在处理以下程序时会遇到困难,但这种方法理解它是安全的:[代码示例]。组借用接受许多通常对借用检查器来说很困难的模式,例如:拥有多个指向同一个对象的局部变量,并通过其中任何一个进行写入(如上所示);获取一个指向对象的参数,以及另一个指向该对象内部某处的参数,并仅通过后者进行写入(我们将在下一节中看到);拥有多个指向同一个对象的函数参数,并通过其中任何一个进行写入;创建一个“回滚”结构体,它会在特定情况下更改对象。