Top
Best
New

Posted by ravenical 11 hours ago

Rust--: Rust without the borrow checker(github.com)
107 points | 164 commentspage 2
ViewTrick1002 9 hours ago|
For everyone unaware, this repo is a meme:

https://www.reddit.com/r/rust/comments/1q0kvn1/corroded_upda...

As a follow on to the corroded meme crate:

https://github.com/buyukakyuz/corroded

> What Is This

> The rust compiler thinks it knows better than you. It won't let you have two pointers to the same thing. It treats you like a mass of incompetence that can't be trusted with a pointer.

> We fix that.

amluto 8 hours ago|
It does seem like satire. The very first example is:

    fn main() {
        let a = String::from("hello");
        let b = a;
        println!("{a}");  // Works! Prints: hello
    }
This is not “I have correct code but Rust can’t tell it’s correct.” This is “wow, this code is intentionally outrageously wrong, obviously dereferences a pointer that is invalid, and happens to work anyway.”
1718627440 48 minutes ago||
> this code is intentionally outrageously wrong

Can you explain why? Why can't both a and b point at the same string object? Does `let b = a;` do something like a destructive move?

kace91 9 hours ago||
I’m not picturing how it works.

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?

gliptic 9 hours ago||
The borrow checker doesn't decide when things are dropped. It only checks reference uses and doesn't generate any code. This will work exactly the same as long as your program doesn't violate any borrowing rules.
kace91 8 hours ago||
No, I get that from an architectural perspective they are separate processes. The point is, unlike in other languages, the compiler is developed assuming the input has been borrow checked, right? So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.
andrewaylett 2 hours ago|||
In a correct program, the borrow checker has no effect.

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.

masklinn 7 hours ago||||
> So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.

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).

pornel 6 hours ago|||
The compiler has deep assumptions about exclusive ownership and moves, which affects destructors and deallocation of objects.

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.

gpm 1 hour ago|||
I'm pretty sure that every example except example-3 in the readme intentionally invokes undefined behavior - if that helps you picture how it works ;)
juliangoldsmith 7 hours ago|||
The silenced errors aren't guaranteed to be memory leaks or use after frees. There are some situations where memory is being handled properly, but the borrow checker isn't able to prove it.

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.

eru 9 hours ago|||
I don't think so, I don't think Rust's borrow checker is free of false negatives.
antonvs 6 hours ago|||
> In other words, are the silenced errors guaranteed to be memory leaks/use after frees?

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.

MangoToupe 8 hours ago||
Rust's concept of lifetime and scopes exists independently of the borrow checker
w4rh4wk5 10 hours ago||
I am wondering whether this would actually be a helpful compile option in upstream rustc for quick prototyping. I don't want prod code to use this, but if I want to try things out during development, this could substantially shorten the dev cycle.
Philpax 9 hours ago||
After a while, you just don't write code that would cause substantial borrow-checker problems, even when prototyping. I'd say the slow compile times are much more of an impediment for a practicing Rust prototyper than the borrow checker.
0xdeafbeef 9 hours ago||
What the point, though? You will get compiling code, but later you would need to reachitecture code to avoid violating rust rules.
withinboredom 9 hours ago||
Sometimes, you just need to know if an idea will even work or what it would look like. If you have to refactor half the codebase (true story for me once), it makes the change a much harder sell without showing some benefits. IE, it keeps you from discovering better optimizations because you have to pay the costs upfront.
eru 9 hours ago|||
Can't you usually just throw some quick referenced counted cells in there, to make the borrow checker happy enough for a prototype without refactoring the whole code base?
LoganDark 8 hours ago|||
In Rust, it's a lot easier to refactor half the codebase than it would be in another language. Once you're done fighting the compiler, you're usually done! instead of NEVER being sure if you did enough testing.
withinboredom 1 hour ago||
I can’t tell if you missed the whole point of “exploratory”…
p0w3n3d 8 hours ago||
There are easier ways of making segfault than writing a custom compiler.
hacker_homie 9 hours ago||
I wish I could make the borrow checker give warnings not errors. It would make exploration so much easier, so I don’t have to fight the borrow checker until I know how to build what I want.
hoppp 9 hours ago|
Then you have code full of warnings and undefined behavior?

I think fighting the borrow checker is more like a rite of passage. Rust is not my favorite language but the borrow checker is great.

leoh 7 hours ago||
This is not a hacker’s take
hoppp 5 hours ago||
I'm lazy. If you turn off the borrow checker the code will need a rewrite later, since it's there for a very good reason.
shmerl 2 hours ago||
Isn't unsafe just for that? Why does it need a separate compiler?
andrewaylett 2 hours ago||
Unsafe isn't so unsafe that it disables the borrow checker!

The two main things the compiler allows in an unsafe block but not elsewhere are calling other code marked "unsafe" and dereferencing raw pointers. The net result is that safe code running in a system that's not exhibiting undefined behaviour is defined to continue to not exhibit undefined behaviour, but the compiler is unable in general to prove that an unsafe block won't trigger undefined behaviour.

You can side-step the borrow checker by using pointers instead of references, but using that power to construct an invalid reference is undefined behaviour.

idontsee 2 hours ago||
The borrow checker still applies in unsafe { } blocks. What it means (iirc) is that you can do pointer/memory stuff that would otherwise not be allowed. But you still fully adhere to Rust semantics
andrewshadura 9 hours ago||
I don’t have a slightest idea why would anyone want this. Borrow checking is one of the greatest benefits of Rust.
Someone1234 9 hours ago|
It is funny.
throwawayffffas 10 hours ago||
It would be great if it only allowed multiple mutable borrows. That's the only one that always bugs me, for mostly innocuous stuff.
threethirtytwo 2 hours ago|
This isn’t actually unsafe unless shared across threads right? Maybe the borrow checker needs to be more nuanced to differentiate this rather then outright banning it all together. It would increase the logic of the borrow checker by a lot though.
fithisux 10 hours ago||
This should be called trust, because it does view the developer as evil.
fithisux 6 hours ago|
I meant "it does not view"
bhaney 10 hours ago|
Are the compile times noticeably faster?
worldsavior 10 hours ago|
Probably not, because it seems like it still checks for errors but just suppresses them.
misnome 9 hours ago||
Even so, the borrow checker repeatedly profiles as an insignificant part of compile times, so wouldn’t make a difference.
More comments...