Purely from a standpoint of terminology, generally, “safety” in Rust means safe from undefined behavior.
Basically, undefined behavior is a contract on the programmer; a compiler promises to produce a reasonably efficient program that performs the instructions written in the code on the condition that the programmer doesn’t do X. The compiler has no obligation to verify that X never occurs (because it may be impossible), and it is given free reign to do anything if it does occur.
This makes bugs caused by undefined behavior often extremely difficult to debug.
Now of course, ultimately this definition doesn’t say much, since the definition of “undefined behavior” depends on the language, and behavior which is “defined but clearly nonsense” (see
So moving away from terminology: Personally, when I call Rust a safe language, I mean that Rust is safer from mistakes. Rust forces me to think upfront about many edge cases that I would otherwise forget about, because it has many good abstractions that encourage correct thinking.
In the end, I find that code I write in rust has fewer bugs to debug than similar code in C/C++, and is more likely to work properly on the first run.
No doubt this is very different from your definition of “safe!”