The Inconceivable Types of Rust: How to Make Self-Borrows Safe

submited by
Style Pass
2024-06-07 21:30:05

One of the first things any Rust programmer learns is that you can’t pass an object and a reference to that object around at the same time. It’s impossible to do, even indirectly. This limitation has been the subject of countless questions on Stack Overflow and posts on Reddit and the Rust forums and anywhere else where Rust programmers might ask for help. It’s so well-known that most people treat it like an axiom, not just a limitation of Rust as it currently exists, but an inherent limitation of borrow checking in general.

However, that’s not the case. In fact, with the right perspective, the way to support it is obvious. In this post, I’ll walk through the steps and show how self-borrows and much more could be supported in a hypothetical alternate or future version of Rust.

To be clear, when I say something can’t be done in Rust, what I mean is that it can’t be done in a safe, zero-cost way. As an army of internet commenters are no doubt rushing to observe, any limitation of a static type system can be bypassed by using unsafety or runtime checks instead (e.g. “lol, just wrap everything in Arc<Mutex<T>>” or “lol, just build your own memory management on top of Vec indices”). And the fact that a less safe or efficient workaround exists is of great interest to people who just need to solve a problem quickly. But from a language design perspective, the pertinent fact is that Rust’s type system has gaps which make certain common tasks impossible to do in a way that lets Rust be Rust, and not just a glorified C or Javascript.

Leave a Comment