Not all safe Rust code is equally safe. This post explains what that means and describes how Rust has a spectrum of safety rather than one that's binary as indicated by the unsafe keyword. The unsafe keyword marks where programmers are given the responsibility to uphold Rust's safety guarantees. Expressed more formally, the soundness guarantees only apply to the safe subset of Rust. This all or nothing approach occurs because once undefined behavior is triggered, it's game over for memory safety. Soundness imposes a hard stop. But Rust does not have a safe/unsafe binary divide. For me, the most surprising case is the consequence of traits being defined as safe, i.e. not marked as unsafe, but allow implementations to cause major problems later on. Specifically, the Eq , Ord and std::hash::Hash traits are allowed to be implemented incorrectly and for those mistakes to cause undefined behavior later on if they're relied on by unsafe code. Because of this unreliability, their documentation includes this warning: The behavior resulting from a logic error is not specified, but users of the trait must ensure that such logic errors do not result in undefined behavior. This means that unsafe code must not rely on the correctness of these methods. In practice, even without the soundness guarantee, we expect code within unsafe blocks to be memory safe. That's because the safety preconditions of that code can be verified by humans, rather than by the compiler. Some coding patterns are more difficult to verify than others. If your unsafe block interacts with a type the implements Eq, then you have additional work to do to ensure memory safety We can use that difficulty quotient as a way to position those patterns along a spectrum. Here is my sketch of that spectrum. It's not an exhaustive list and many items could be reordered (comments and thoughts are welcome!). some of the labels, such as "Pointer Poker" and "Axiom", are my creations. Spectrum of Safety (v0.1) Behind the unsafe keyword Raw Assembly I'm going to place this on the most dangerous part of the spectrum because it places the biggest demands on code reviewers. Few people are specialists in assembly languages these days and instruction sets are much more complicated than when assembly language was common place. Pointer Poker Using raw pointers and type casting to do whatever you want can be wildly dangerous. Unsafe Most unsafe code lives here. Partial Initialization Some patterns of interacting with uninitialized memory are easy to review for soundness. Therefore, I am inclined to suggest that using unsafe for partial initialization is on the safer side of the spectrum. Like-for-like FFI The FFI boundary is a fairly mystical one with many hidden traps, but there some foreign functions are easier than others. For example, if a library only dealt with with primitive types, you're less likely to trigger undefined behavior than one that involves lots of indirection through pointers. Experimental or Internal APIs An occasional use of the unsafe keyword is to mark a SemVer boundary, rather than to mark an area that imposes memory safety guarantees. This is stronger than using a feature flag, but it's not the intended purpose of the keyword. Beyond the unsafe boundary: "Semver exempt" APIs Many projects want to exclude some types from complying with semantic versioning requirements. There is only limited support for this in the language, i.e. the #[non_exhaustive] attribute on enums. That forces ad-hoc methods of describing this, such as documentation ("DO NOT rely on the stability of this method ...") and items being hidden from public view with #[doc(hidden)]. Unreliable Traits These traits must not be relied on within unsafe code. Eq and Ord are the most obvious examples. Sealed Traits A so-called "sealed trait" is one that can only be implemented on types from the crate that defines the trait. It adds a Safe Rust This is where most Rust programmers spend most of their time. Axiom All code reviewers of unsafe code can be assured that the operation returns the correct value. A note on the "Axiom" level of safety A way to mark an axiomatic operation is something which doesn't exist in the Rust language syntax, but I expect proposals to emerge over the long term. Some operations are so fundamental that it would be impossible to rely on any unsafe code if their implementation couldn't be relied upon, such as integer addition the add method on raw pointers . I like the name "axiom" rather than something like "verified" or "assured" because it places an extremely high bar on which operations are allowed to be considered as axiomatic. Formal verification is is probably the route that's needed to get there though.. which is what reminds me that I had a chat with one of its strongest proponents that might be interesting to listen to: