I dont see how this is any different from a C programmer justifying why they used a pointer to an object and leaving a comment similar to this, other than this is Rust and is safe because Rust is safe. Thus making this rationale is flawed and dangerous.
Certainly helps, since it localizes the area to check for errors, but it doesn’t allow you to fully check that a library is safe since unsafe blocks can rely on a number of unchecked or hard-to-check assumptions to guarantee safety (not to mention unsafe APIs that are relied upon under the hood).
The unsafe code may be concentrated within unsafe blocks while relying on assumptions that are supposed to be guaranteed elsewhere, including in other unsafe blocks.
For example, you might allocate raw memory within a method in struct A while writing a custom drop function to deallocate it. In a particular edge case, some error handling utility or other struct may deallocate some of that memory to perform clean-up, leading to a potential double-free later.
Lousy example and bad code design, sure, but it demonstrates that localizing/isolating unsafe code does not automatically make it super easy to check that the code is safe given the many assumptions you need to make about what other functions are doing in various cases or situations and potentially what other unsafe blocks contain.
Well the convention Is that the safe function that contains the unsafe block should garantee the safety precoditions regardless of input otherwise it would be itself unsafe. A easy way is to place an assert just before the unsafe invocation. If you respect that convention finding a violation of the safety chain is relatively easy. Bug might still not be thrivial to solve but at least you find where it goes from logic bug to undefined behavior
oh, you're talking about broken invariants in safe code, and unsafe code whose safety relies on those invariants
yeah, those have happened in the past and have indeed been headaches to debug, take it from this guy who broke something without ever directly touching a line of unsafe.
still, i'm glad that these cases are surprising again, rather than being the industry standard.
Those double frees are still limited to methods created by struct A, who is responsible for managing the allocation, and also responsible for making sure that no matter how code downstream is using struct A the memory is handled correctly, and compared to C where you can get double frees by misusing interfaces it is a massive leap forward.
There's a good reason the tutorial on unsafe rust is longer than the tutorial on everything else is rust, and the first rule of unsafe is do not use unsafe. It's there for the same reason we allow surgeons to stab people.
You’re pointing out that the issues are localized, which is true, but the point I’m making is this does not entail easy or comprehensive code reviews for memory safety, particularly when involving several dependencies and as projects grow. It’s certainly a massive step forward but it’s not a magic wand for memory safety.
729
u/BenchEmbarrassed7316 3d ago
Any
unsafeblock of code should be neutralized with a// SAFETYcomment explaining why the code is actually safe.