Posted by ravenical 1/1/2026
I really miss these when doing concurrent stuff in other languages.
If Rust were to "borrow" something from the C/C++ spirit, then disabling the borrow checker should be available as a compiler option.
As in, you're an adult: if you want it, you can have it, instead of "we know better".
You can already disable it locally: the unsafe keyword is for that.
It doesn't make much sense to globally relax restrictions of Rust's references to be like C/C++ pointers, because the reference types imply a set of guarantees: must be non-null (affects struct layout), always initialized, and have strict shared/immutable vs exclusive access distinction. If you relax these guarantees, you'll break existing code that relies on having them, and make the `--yolo` flag code incompatible with the rest. OTOH if you don't remove them, then you still have almost all of borrow checker's restrictions with none of the help of upholding them. It'd be like a flag that disables the sign bit of signed integers. It just makes an existing type mean something else.
You don't technically. The borrow checker doesn't effect the semantics of the program (like, for example, type inference does) and the rest of the compiler doesn't need to (and in fact, doesn't) use its analysis to figure out how to compile the code.
The downstream compiler does assume that the code followed the rules for accessing references - i.e. didn't violating aliasing rules. The borrow checker guarantees this, but it's fundamentally a conservative check. It rejects programs it can't guarantee are correct, and rice's theorem proves that there are always correct programs that it can't guarantee are correct.
That said if you just treat rust-references like C-pointers you will run into issues. The aliasing rules for rust references are stricter. Also not fully agreed upon yet - the currently closest to accepted definition is in the "tree borrows" paper but it has yet to be adopted as the official one by the rust team.
If we can't have this, C itself offers zero benefit over assembly.
Because it's fun.
I can totally understand why you wouldn't want to do this though - the plethora of incompatible lisp dialects come to mind. That's why I said it was controversial.
Those are two reasons why C is less tedious than assembly.
Have you heard of longjmp?
In rust you don’t have a garbage collector and you don’t manually deallocate - if the compiler is not certain of who drops memory and when, what happens with those ambiguous drops ?
In other words, are the silenced errors guaranteed to be memory leaks/use after frees?
Languages like C compile code with the understanding that if the compiler can't prove the code is incorrect, it'll assume it's correct. Rust compiles with the expectation that unless the compiler can prove the code correct (according to the language rules), it won't compile it. In C, all programs that only perform defined behaviour are valid, but many programs which exhibit undefined behaviour are also valid. In safe Rust, all programs which exhibit undefined behaviour are invalid. But as a trade-off, many programs which would actually execute perfectly well are also considered invalid.
In both cases, once you get past the layers that check stuff, you may normally assume that whatever you have has already been shown to be OK and you probably don't have enough information to re-check while compiling. It might blow up at runtime, it might not.
The final program may be broken in various manners because you don't respect the language's prescribed semantics, in about the same way they do in C and C++. From the compiler's perspective the borrow checker validates that rules it assumes are upheld are actually upheld.
mrustc already compiles rust code without having a borrow checker (well IIRC recent-ish versions of mrustc have some borrow checking bits, but for the most part it still assumes that somebody else has done all the borrow checking).
It doesn't actually depend on the borrow checker. All lifetime labels are discarded after being checked. Code generation has no idea about borrow checking. Once the code is checked, it is compiled just like C or C++ would, just assuming the code is valid and doesn't use dangling pointers.
Borrow checker doesn't affect program behavior. It either stops compilation or does nothing at all. It's like an external static analysis tool.
No, not at all. The examples at the beginning of the article show this - they'll execute correctly. The borrow checker is quite conservative, and rules out all sorts of code that won't (normally!) cause runtime errors.
It's fairly easy to see this if you think about the core of Rust's ownership model: every value in Rust has a single owner. The compiler enforces that for any value, there's either one mutable reference or any number of immutable references to it at a time.
This model has the advantage of being simple, easy to reason about, and ruling out large classes of errors. But like most static checks, including e.g. traditional type checks, it also rules out a great deal of otherwise valid code.
It's easy to think of examples in which you have multiple mutable references to a value that won't cause errors. Aside from trivial examples like in the article, in C-like languages you can have many concurrent mutable references to the same mutable value. You can safely (with some caveats) manage access to it via locks, protocols, documentation, or just being careful. Rust with the borrow checker simply doesn't allow multiple concurrent mutable references to the same value to exist. Rust without the borrow checker, as in the article, would allow this.
One example might be a tree-like struct where a parent and child have references to each other. Even if everything is cleaned up properly, the borrow checker has no way to know that when the struct is created. Solving it requires unsafe at some point, usually through something like RefCell.
Sometimes I will prototype an exploration in another crate or module so I can see if there are performance gains in a more limited application. Sometimes these explorations will grow into a full rewrite that ends up better than if I had refactored.
I think what GP is trying to say is that the value of such exploration might be limited if you end up with something incompatible with "proper" Rust anyways.
I suppose it depends on how frequently "transition through invalid Rust while experimenting and end up with valid Rust" happens instead of "transition through invalid Rust while experimenting and end up with invalid Rust", as well as how hard it is to fix the invalid Rust in the latter case.
That being said, I think what you describe sounds like a case where relaxed checks could be beneficial. It's the eternal tradeoff of requiring strong static checks, I suppose.