The basic idea is that there are invariants that the language / compiler relies upon. Arguably the most fundamental is that &mut _
references are unique / not aliased. But there are many others, like &_
is always aligned and non-null; the bitwise value of a bool
is 1 or 0; etc.
When you use safe Rust, the compiler proves that your program is, to some extent, correct -- it contains no undefined behavior (UB). It might still have logic errors, but no UB. In Rust that includes "memory safety" errors like use-after-free and reading of uninitialized data, as well as other things like data races. It knows how to analyze safe Rust and prove that all the invariants hold. If the compiler can't prove it, you get an error (borrow checker error, Sync
not implemented error, ...).
But the compiler can't prove that every correct program is, in fact, correct. And since Rust is a systems language that allows access to the system libraries, allocators, assembly, and so on, this is considered an unacceptable limitation. So Rust gives programmers a way to "turn off" the proof engine: unsafe
.
But this does not change the invariants. Instead, it is now the responsibility of the programmer to uphold the invariants.
In my opinion, unsafe
Rust is very hard to get right, at least, beyond some trivialities like vec.get_unchecked(0)
or perhaps well-trod areas like FFI. So yes, I would say it is difficult to utilize correctly. You must understand a lot and be conservative to get it right. Hopefully this will improve over time, with a more thorough specification of the language and more compiler guidance (warnings) for unsafe
code. Currently, you are largely on your own.
Definitely it is not something you should reach for whenever you get some borrow check error, say.
A big benefit of unsafe
code is encapsulation. If you have a program that exhibits UB, you know that the cause is in some unsafe
block somewhere. If you do not use unsafe
yourself, you know it's not your fault -- it's a bug in some dependency.
The ideal is for unsafe
to be encapsulated in targeted, well-tested, and battle-hardened libraries. Then the vast majority of Rust programs need not contain any local unsafe
; instead they build on the libraries.