Course contentsShow
← Rust
Lesson 706 of 1,9106. Generics and Static DispatchFree lesson

Generic Self Types

Utilize self-referential bounds to define methods that return the implementor type.

Mastering Generic Self Types

In this lesson, you will learn how to use the special Self keyword to define methods that return the exact type that implements a trait, ensuring type consistency across your generic abstractions.

The Problem of Rigid Returns

When you write a trait, you often want methods to return an instance of the type performing the action. If you manually type the struct name (e.g., impl MyTrait for MyStruct { fn clone(&self) -> MyStruct }), you lose flexibility. If you later rename your struct, your trait implementation breaks. Even worse, if you try to use a generic parameter to represent the return type, the compiler won't know if that parameter matches the type currently implementing the trait.

Introducing Self

The Self keyword (capitalized) acts as a type alias for "the type that is currently implementing this trait." It is a self-referential bound that allows your methods to return the implementor type without needing to know its name.

Consider a simple Builder pattern:

trait Builder {
    fn new() -> Self;
    fn increment(self) -> Self;
}

struct Counter(i32);

impl Builder for Counter {
    fn new() -> Self {
        Counter(0)
    }

    fn increment(self) -> Self {
        Counter(self.0 + 1)
    }
}

In the example above, Self tells the compiler: "Whatever type implements Builder, this method returns that same type."

Why Use It?

  1. Safety: It prevents you from accidentally returning a different type than the one being used.
  2. Readability: It makes it clear that the method is a transformation or a constructor for the current type.
  3. Generics Integration: When you use Self, you are creating a static dispatch bond. Because the compiler knows exactly what Self is at the time of implementation, it can optimize the code during compilation, replacing the Self placeholder with the concrete type.

By using Self, you write generic traits that are robust, reusable, and perfectly aligned with the structures that implement them.

Key Takeaway: Use the Self keyword as a type alias to refer to the implementor of a trait, allowing your methods to return the exact type that is currently performing the implementation.