Common Rust Lifetime Misconceptions
Posted by CafeRacer 8 hours ago
Comments
Comment by qouteall 28 minutes ago
Contagious borrow issue is a common problem for beginners.
Comment by nromiun 3 hours ago
This was my biggest problem when I used to write Rust. The article has a small example but when you start working on large codebases these problems pop up more frequently.
Everyone says the Rust compiler will save you from bugs like this but as the article shows you can compile bugs into your codebase and when you finally get an unrelated error you have to debug all the bugs in your code. Even the ones that were working previously.
> Rust does not know more about the semantics of your program than you do
Also this. Some people absolutely refuse to believe it though.
Comment by MrJohz 1 hour ago
However, you've still got to do that job of encoding the semantics. Moreover, the default semantics may not necessarily be the semantics you are interested in. So you need to understand the default semantics enough to know when you need something different. This is the big disadvantage of lifetime elision: in most cases it works well, but it creates defaults that may not be what you're after.
The other side is that sometimes the semantics you want to encode can't be expressed in the type system, either because the type system explicitly disallows them, or because it doesn't comprehend them. At this point you start running into issues like disjoint borrows, where you know two attributes in a struct can be borrowed independently, but it's very difficult to express this to the compiler.
That said, I think Rust gives you more power to express semantics in the type system than a lot of other languages (particularly a lot of more mainstream languages) which I think is what gives rise to this idea that "if it compiles, it works". The more you express, the more likely that statement is to be true, although the more you need to check that what you've expressed does match the semantics you're aiming for.
Comment by LtdJorge 3 hours ago
Of course, if your program compiles, that doesn't mean the logic is correct. However, if your program compiles _and_ the logic is correct, there's a high likelihood that your program won't crash (provided you handle errors and such, you cannot trust data coming from outside, allocations to always work, etc). In Rust's case, this means that the compiler is much more restrictive, exhaustive and pedantic than others like C's and C++'s.
In those languages, correct logic and getting the program to compile doesn't guarantee you are free from data races or segmentation faults.
Also, Rust's type system being so strong, it allows you to encode so many invariants that it makes implementing the correct logic easier (although not simpler).
Comment by irishcoffee 7 minutes ago
That is one hell of a copium disclaimer. "If you hold it right..."
Comment by wakawaka28 49 minutes ago
I don't believe that it's guaranteed in Rust either, despite much marketing to the contrary. It just doesn't sound appealing to say "somewhat reduces many common problems" lol
>Also, Rust's type system being so strong, it allows you to encode so many invariants that it makes implementing the correct logic easier (although not simpler).
C++ has a strong type system too, probably fancier than Rust's or at least similar. Most people do not want to write complex type system constraints. I'm guessing that at most 25% of C++ codebases at most use complex templates with recursive templates, traits, concepts, `requires`, etc.
Comment by alkonaut 3 hours ago
Comment by embedding-shape 2 hours ago
Rust programs can't know what you want to do, period.
Comment by qouteall 27 minutes ago
https://qouteall.fun/qouteall-blog/2025/How%20to%20Avoid%20F...
Comment by throwawayqqq11 2 hours ago
Soundness does not cover semantic correctness. Maybe you want to wipe $HOME.
Comment by wakawaka28 1 hour ago
It depends on what you mean by "freed". Can one write a custom allocator in Rust? How does one handle reading from special addresses that represent hardware? In both of these scenarios, one might read from or write to memory that is not obviously allocated.
Comment by littlestymaar 3 hours ago
It's just that once it compiles Rust code will work more often than most languages, but that doesn't mean Rust code will automatically be bug free and I don't think anyone believes that.
Comment by embedding-shape 2 hours ago
- https://bsky.app/profile/codewright.bsky.social/post/3m4m5mv...
- https://bsky.app/profile/naps62.bsky.social/post/3lpopqwznfs...
Comment by muixoozie 1 hour ago
Comment by goku12 1 hour ago
But I have not seen any resource or anyone making technical points ever assert that the Rust compiler can verify program logic. That doesn't even make sense - the compiler isn't an AI that knows your intentions. Everybody is always clear that it only verifies memory safety.
Now regarding the 'most of the time' part. The part below is based purely on my experience and your mileage may vary. It's certainly possible to compile Rust programs with logical/semantic errors. I have made plenty. But the nature of C/C++ or similar manually memory-managed languages is such that you can make memory safety bugs quiet easily and miss them entirely. They also stay hidden longer.
And while logical errors are also possible, most people write and test code in chunks of sizes small enough where they feel confident enough to understand and analyze it entirely within their mind. Thus they tend to get caught and eliminated earlier than the memory safety bugs.
Now since Rust handles the memory safety bugs for you and you're reasonably good at dealing with logical bugs, the final integrated code tends to be bug-free, surprisingly more often than in other languages - but not every time.
There is another effect that makes Rust programs relatively more bug-free. This time, It's about the design of the code. Regular safe Rust, without any runtime features (like Rc, Arc, RefCell, Mutex, etc) is extremely restrictive in what designs it accepts. It accepts data structures that have a clear tree hierarchy, and thus a single-owner pattern. But once you get into stuff like cyclic references, mutual references, self references, etc, Rust will simply reject your code even if it can be proven to be correct at compile time. You have three options in that case: Use runtime safety checks (Rc, RefCell, Mutex, etc. This is slightly slower) OR use unsafe block and verify it manually, OR use a library that does the previous one for you.
Most of the code we write can be expressed in the restricted form that safe Rust allows without runtime checks. So whenever I face such issues, my immediate effort is to refactor the code in such way. I reach for the other three methods only if this is not possible - and that's actually rare. The big advantage of this method is that such designs are relatively free of the vast number of logical bugs you can make with a non-tree/cyclic ownership hierarchy. (Runtime checks convert memory safety bugs into logical bugs. If you make a mistake there, the program will panic at runtime.) Therefore, the refactored design ends up very elegant and bug-free much more often than in other languages.
Comment by spoiler 2 hours ago
But I don't doubt there are people who take that phrase too literally, though.
Comment by littlestymaar 2 hours ago
I think is is a fairly bad example to pick, because the fact that the person says “I can basically think” and “most of the time it does” (emphasis mine) shows that they don't actually believes it will makes bug-free programs.
They are just saying that “most of the time” the compiler is very very helpful (I agree with them on that).
Comment by emilbratt 3 hours ago
Comment by hsywuwuf 3 hours ago
Comment by simonask 3 hours ago
> Others think someone from the Rust (programming language, not video game) development community was responsible due to how critical René has been of that project, but those claims are entirely unsubstantiated.
What is this culture war you're fighting?
Comment by Tuna-Fish 3 hours ago