Comment by bit1993
Ah. I agree with you. When unsafe is used the borrow checker cannot check for memory safety, the programmer has to provide the guarantees by making sure their code does not violate memory safety, similar to programming in C.
But unsafe Rust is still far better than C because the unsafe keyword is visible and one can grep it and audit the unsafe parts. Idiomatic Rust also requires that the programmer provides comments as to why that part is unsafe.
I think making things more explicit with "unsafe" is an advantage of Rust, but I think "far better" is a bit of an exaggeration. In C you need to audit pointer arithmetic, malloc/free, casts and unons. If you limit pointer arithmetic to a few safe accessor functions and have a documented lifetime rules, this is also relatively simple to do (more difficult than "grep" but not much). Vice versa, if you use a lot of "unsafe" in Rust or in complicated ways, it can also easily become possible to guarantee safety. In contrast to what people seem to believe, the bug does not need to be inside in unsafe block (a logic error outside can cause the UB inside unsafe or a violation of some of Rust's invariants inside unsafe can allow UB outside of unsafe) and can result even from the interaction of unsafe blocks.
The practical memory safety we see in Rust is much more the result of trying hard to avoid memory safety issues and requiring comments for unsafe blocks is part of this culture.