Course contentsShow
← Rust
Lesson 557 of 1,9105. Type System and TraitsFree lesson

Unpin Trait and Memory Safety

Identify when types can be safely moved despite pinning constraints.

In this lesson, you will learn how the Unpin trait acts as a "safety switch" that tells the Rust compiler whether a type can be safely moved even when it is wrapped in a Pin pointer.

The Problem with Moving

In Rust, most types are "movable" by default. If you move a struct, the compiler just performs a memcpy to the new location. However, some types are self-referential (a field contains a pointer to another field within the same struct). If you move such a struct, that internal pointer becomes invalid, leading to instant memory unsafety. Pin exists to stop these types from being moved.

The Unpin Trait

The Unpin trait is a marker trait—it contains no methods. It is an auto-trait, meaning the compiler automatically implements it for almost every type. If a type implements Unpin, it means: "Even if this is wrapped in a Pin pointer, it is safe to move."

Most types, like i32, String, or standard structs, are Unpin. They don't have self-referential requirements, so Pin<Box<i32>> behaves just like a regular Box<i32>.

When is a type NOT Unpin?

A type only loses its Unpin status if it is explicitly designed to be self-referential (such as types generated by async blocks or certain state machines).

Consider this comparison:

use std::marker::PhantomPinned;

// This type is NOT Unpin because of PhantomPinned
struct SelfReferential {
    _marker: PhantomPinned, 
}

fn process_data<T>(data: Pin<&mut T>) 
where T: Unpin 
{
    // Because of the Unpin bound, we know it's safe 
    // to move or access the value directly here.
}

If you try to pass a non-Unpin type into a function that requires Unpin, the compiler will stop you. This protects you from accidentally moving a self-referential structure that would break its internal pointers.

In short, you don't usually need to implement Unpin yourself. Instead, you rely on it as a trait bound to tell your generic code: "I am okay working with this pinned type because it doesn't have unstable internal pointers."

Key Takeaway: The Unpin trait is the mechanism that signals a type is safe to move, even when pinned; almost all types are Unpin by default, protecting you from memory unsafety only when you specifically opt into self-referential structures.