Using the `unsafe` keyword and undefined behaviour
In the recent big thread about the use of Rust for game development, the lead author of the popular \Bevy\\ crate (u/\_cart) made a comment that concluded with the following quote, which I think is really great, and something which maybe isn't emphasized often enough to new crustaceans:
Additionally, if you really don't care about safety (especially if you're at the point where you would prefer to move to an "unsafe" language that allows multiple mutable borrows), you always have the
get_uncheckedescape hatch in Bevy:
unsafe {
let mut e1 = entities.get_unchecked(id1).unwrap();
let mut e2 = entities.get_unchecked(id2).unwrap();
let mut mob1 = e1.get_mut::<Mob>().unwrap();
let mut mob2 = e2.get_mut::<Mob>().unwrap();
}
In the context of "screw it let me do what I want" gamedev, I see no issues with doing this. And when done in the larger context of a "safe" codebase, you can sort of have your cake and eat it too.
Whilst this is great advice, it obviously also has its caveats. One of the caveats that I have ran into is that inside an \unsafe\\ block it's really easy to run into undefined behaviour. For example a while ago I discussed a performance improvement a colleague made in the Rust discord, and the conclusion was that their use of writing to mut references without using something like UnsafeCell relied on undefined behaviour, and might randomly stop working in some future rustc/llvm release.
From my perspective, there were two big issues the Rust language itself might have helped with:
There's a big difference between unsafe code that does thing the Rust compiler can't verify are correct, and things that are UB. Could the compiler somehow tell the difference?
The code with UnsafeCell was a \lot\ more complex than the code written in C style. This might be very specific to this specific performance optimisation, but it's a bit of a downer. When we as the Rust community say "Oh doing perf optimisations is as easy as it is in C, just use the \
unsafe\\keyword", but then UB makes it so that it's actually a lot more difficult still than it would be in C it doesn't reflect well on the language.
Are there any efforts in the Rust language to address these problems? Are they on anyones radar or are they simply intractable?