There are also some usages of `unsafe` for constructs (like linked lists) that the borrow-checker does not support. Those could theoretically be checked, but as far as I know a practical/pragmatic way of doing that has yet to be invented.
In a practical sense, in order to not have “unsafe” code, the language specification would have to contain a full formal specification of every aspect that it’s running on. The hardware, the system software you rely on, everything. That isn’t a good idea, so no language does it. And it doesn’t help you when new hardware comes out.
In a more formal sense, you run into things like Rice’s theorem.
This is a pretty weak argument. "Everyone else does it, so it's not wrong." If using this argument, Rust shouldn't even exist.
Rice's theorem seems handwavy in the real-world limitations of its restrictions. For the sake of argument, even Python is more memory-safe than unsafe Rust.