With all due respect, I
do think you're conflating the way things are with the way things have to be.
glibc has a similar commitment to never breaking user code, and yet symbols have been removed from glibc! The trick is to use "symbol versioning"; code compiled against old versions of glibc is transparently rewritten to use the old versions of symbols, while code compiled against new versions is rewritten to use the new versions of the symbols. [0][1]
You can imagine something similar for the Rust standard library, whereby both the unsafe and safe versions are provided, and packages are transparently rewritten to use the correct version based on their specified edition. You don't need two copies of the stdlib; just of the symbols that have diverged. In this case, you wouldn't even need two versions of the symbol in the resulting binary, since the addition of `unsafe` doesn't change the codegen of the function, but merely restricts what code is accepted by the compiler.
It's true that this would require some serious shenanigans in the stdlib, but it's a tractable problem. It's also, in my mind, quite acceptable for the standard library to play games like this, since the compiler, the language, and the stdlib are always going to be tightly coupled, and the complexity can be shielded from users.
All that said, it sounds like the list of deprecated stdlib features is nowhere near long enough to justify adding this kind of complexity.
[0]: https://gcc.gnu.org/wiki/SymbolVersioning
[1]: Note that symbol versioning is kind of a quagmire, but that's because it's seriously underdocumented and practically no developers are aware that it exists. The idea itself is sound.