Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An unsafe trait is a trait containing specific semantic invariants that the Rust compiler cannot automatically verify. By marking a trait with the unsafe keyword, the author dictates that any implementation of this trait must also be explicitly marked as unsafe. This transfers the responsibility of upholding the trait’s compiler-invisible contracts from the compiler to the implementer.

Syntax and Declaration

To define an unsafe trait, the unsafe keyword precedes the trait declaration:
unsafe trait ValidatesInvariants {
    fn perform_action(&self);
}
To implement this trait, the implementer must use an unsafe impl block. This acts as an explicit acknowledgement by the developer that they have read the trait’s documentation and guarantee that the type fulfills all required invariants.
struct MyType;

// The implementer assumes responsibility for the trait's invariants
unsafe impl ValidatesInvariants for MyType {
    fn perform_action(&self) {
        // Method implementation
    }
}

Orthogonality of Unsafe Traits and Unsafe Methods

A critical mechanical distinction in Rust is the separation between unsafe traits and unsafe methods. The unsafe keyword applies strictly to the boundary it modifies:
  1. Unsafe Trait (unsafe trait): The danger lies in implementing the trait incorrectly. Calling the methods on the trait is entirely safe, provided the implementer upheld the contract.
  2. Unsafe Method (unsafe fn): The danger lies in calling the method. Implementing the trait is safe, but the caller must uphold specific preconditions before invoking the function.
// 1. Unsafe to implement, safe to call
unsafe trait TrustMe {
    fn safe_to_call(&self); 
}

// 2. Safe to implement, unsafe to call
trait BeCareful {
    unsafe fn unsafe_to_call(&self);
}

// 3. Unsafe to implement, unsafe to call
unsafe trait ExtremeCaution {
    unsafe fn unsafe_to_call(&self);
}

Auto Traits and Unsafe

In Rust’s type system, marker traits like Send and Sync are implemented as unsafe auto trait. The compiler automatically implements these traits for types composed entirely of other Send/Sync types. However, if a developer needs to manually implement an auto trait for a type that the compiler rejects (e.g., a struct containing raw pointers), they must bypass the compiler’s safety checks using an unsafe impl.
struct RawWrapper {
    ptr: *mut u8,
}

// The compiler will not auto-implement Send because of the raw pointer.
// The developer must use `unsafe impl` to assert thread-safety invariants manually.
unsafe impl Send for RawWrapper {}

Supertraits and Unsafe

If a safe trait relies on an unsafe trait as a supertrait, implementing the safe trait does not require the unsafe keyword. However, the type must still provide an unsafe impl for the underlying unsafe supertrait.
unsafe trait BaseUnsafe {}

// Safe trait with an unsafe supertrait
trait DerivedSafe: BaseUnsafe {}

struct Data;

// Requires unsafe
unsafe impl BaseUnsafe for Data {}

// Does not require unsafe
impl DerivedSafe for Data {}
Master Rust with Deep Grasping Methodology!Learn More