Question

Difference Between `self` and `Self` in Rust

Question

In Rust, what is the difference between self and Self?

I have seen Self used in source code, but most documentation examples use self. I want to understand what each one means, where they are used, and when I should choose one over the other.

Short Answer

By the end of this page, you will understand that self and Self are different concepts in Rust. self usually refers to the current instance inside a method, while Self refers to the current type inside an impl block or trait. You will see where each is used, how their syntax differs, and how they appear in real Rust code.

Concept

In Rust, self and Self are related, but they mean different things.

  • self refers to the current value or instance of a type.
  • Self refers to the type itself.

This distinction matters because Rust makes a clear separation between:

  • a value created from a type
  • the type definition itself

self means the current instance

You use self in methods when you want to work with the object the method was called on.

For example:

struct User {
    name: String,
}

impl User {
    fn greet(&self) {
        println!("Hello, {}", self.name);
    }
}

Here:

  • &self means the method borrows the current User
  • self.name accesses a field on that specific instance

Self means the current type

You use Self when you want to refer to the type currently being implemented.

struct User {
    name: String,
}

impl User {
    fn new(name: String) -> Self {
        Self { name }
    }
}

Here:

  • -> Self means the function returns a User
  • Self { name } constructs a User value

Inside impl User, Self is another way to write User.

Why Rust has both

Rust uses both because they solve different problems:

  • self helps you work with the current object instance
  • Self helps you write reusable, type-based code

This is especially useful in traits, where the exact implementing type may not be known in advance.

trait Animal {
    fn create() -> Self;
}

In this trait, Self means "whatever type implements this trait." That would not be possible if Rust required a concrete type name here.

Mental Model

Think of a class blueprint and a built object.

  • Self is the blueprint name: the type itself
  • self is the actual object in your hands

If you build a Car:

  • Self means Car
  • self means a specific car, such as your blue car parked outside

So:

  • use Self when talking about what kind of thing it is
  • use self when talking about the current thing itself
Take Quiz

Syntax and Examples

Core syntax

Using self in methods

struct Counter {
    value: i32,
}

impl Counter {
    fn show(&self) {
        println!("{}", self.value);
    }

    fn increment(&mut self) {
        self.value += 1;
    }

    fn consume(self) {
        println!("Final value: {}", self.value);
    }
}

What these mean

  • &self borrows the current instance immutably
  • &mut self borrows the current instance mutably
  • self takes ownership of the current instance

Using Self in return types and constructors

struct Counter {
    value: i32,
}

impl Counter {
    fn new() -> Self {
        Self { value: 0 }
    }
}

This is equivalent to:

impl Counter {
    fn new() -> Counter {
        Counter { value: 0 }
    }
}

Using Self is often preferred because it is shorter and still correct if the type name changes later.

Trait example

trait Resettable {
    fn reset() -> Self;
}

struct Counter {
    value: i32,
}

impl Resettable for Counter {
    fn reset() -> Self {
        Self { value: 0 }
    }
}

Here Self means the implementing type, which is Counter in this implementation.

Step by Step Execution

Consider this example:

struct Book {
    title: String,
}

impl Book {
    fn new(title: String) -> Self {
        Self { title }
    }

    fn print_title(&self) {
        println!("{}", self.title);
    }
}

fn main() {
    let book = Book::new(String::from("Rust Basics"));
    book.print_title();
}

Step by step:

  1. struct Book defines a type named Book.
  2. Inside impl Book, Self refers to the type Book.
  3. fn new(title: String) -> Self says that new returns a Book.
  4. Self { title } creates a Book value using the provided title.
  5. In main, Book::new(...) creates a new Book instance.
  6. The variable book now holds that instance.
  7. book.print_title() calls a method on that instance.
  8. Inside print_title, &self is a reference to the book instance.
  9. self.title reads the title field from that specific Book.
  10. The program prints Rust Basics.

The key idea is:

  • Self was used when referring to the type being created
  • self was used when referring to the specific value being used

Real World Use Cases

You will commonly see self and Self in these situations:

Struct methods

impl Config {
    fn validate(&self) -> bool {
        !self.path.is_empty()
    }
}

Use self because the method checks data on the current instance.

Constructors and factory methods

impl Config {
    fn default() -> Self {
        Self {
            path: String::from("./app.conf"),
        }
    }
}

Use Self because the function returns a new value of the type.

Trait definitions

trait Parseable {
    fn parse(input: &str) -> Self;
}

Use Self because the trait does not know in advance which concrete type will implement it.

Builder-style APIs

impl Query {
    fn limit(mut self, amount: usize) -> Self {
        self.limit = amount;
        self
    }
}

Here both appear:

  • self is the current value being modified
  • Self is the return type

This is very common in fluent APIs.

Take Quiz

Real Codebase Usage

In real Rust projects, developers use self and Self in predictable patterns.

Instance methods

Methods that inspect or modify fields usually take one of these forms:

  • &self for read-only access
  • &mut self for modification
  • self when consuming the value
impl Session {
    fn is_expired(&self) -> bool {
        self.expires_at < 1000
    }

    fn refresh(&mut self) {
        self.expires_at += 3600;
    }
}

Constructors and named constructors

impl Session {
    fn new() -> Self {
        Self { expires_at: 0 }
    }
}

This keeps code easier to refactor than repeating the type name.

Trait-based abstractions

Self is heavily used in traits for return values and associated behavior.

trait Serializable {
    fn from_bytes(bytes: &[u8]) -> Self;
}

Method chaining

Developers often return Self from methods that transform values.

impl Options {
    fn enable_logs(mut self) -> Self {
        self.logs = true;
        self
    }
}

Error handling and validation

self is often used with guard clauses to check the current state.

impl Request {
    fn send(&self) -> Result<(), String> {
        if self.url.is_empty() {
            return Err(String::from("URL cannot be empty"));
        }
        Ok(())
    }
}

Common Mistakes

1. Thinking self and Self are interchangeable

They are not.

  • self is a value
  • Self is a type

Broken example:

struct User;

impl User {
    fn make() -> self {
        self
    }
}

This is invalid because self is not a type.

Correct version:

struct User;

impl User {
    fn make() -> Self {
        Self
    }
}

2. Using self outside a method receiver context incorrectly

Broken example:

struct User {
    name: String,
}

impl User {
    fn print_name() {
        println!("{}", self.name);
    }
}

This fails because there is no self parameter.

Correct version:

impl User {
    fn print_name(&self) {
        println!("{}", self.name);
    }
}

3. Forgetting that Self depends on context

Inside impl User, Self means User. Inside impl Trait for User, Self also means User. Inside a trait definition, Self means the unknown implementing type.

4. Confusing self with ownership rules

These are different:

fn read(&self)
fn change(&mut self)
fn take(self)

The difference here is not about self versus Self, but about how the instance is passed.

5. Overusing the concrete type name instead of Self

This is valid:

impl User {
    fn new() -> User {
        User
    }
}

But this is often more maintainable:

impl User {
    fn new() -> Self {
        Self
    }
}

If the type name changes later, fewer places need updating.

Comparisons

ConceptMeaningUsed forExample
selfThe current instance/valueAccessing fields and calling instance logicself.name
SelfThe current typeReturn types, constructors, trait definitionsfn new() -> Self

self receiver forms

SyntaxMeaning
&selfBorrow the current instance immutably
&mut selfBorrow the current instance mutably
selfTake ownership of the current instance

Self vs concrete type name

OptionExampleWhen to use
Selffn new() -> SelfPreferred inside impl and traits
Concrete typefn new() -> UserSometimes used for clarity, but usually less flexible

Quick rule

  • If you mean the object/value, use self
  • If you mean the type, use Self
Take Quiz

Cheat Sheet

  • self = the current instance
  • Self = the current type

Common patterns

fn show(&self)
fn update(&mut self)
fn consume(self)
fn new() -> Self

Examples

impl User {
    fn new(name: String) -> Self {
        Self { name }
    }

    fn greet(&self) {
        println!("Hi, {}", self.name);
    }
}

Remember

  • self.name accesses a field on the current value
  • Self { ... } constructs a value of the current type
  • In traits, Self means "the type that implements this trait"
  • self cannot be used as a type name
  • Self cannot access instance fields directly

Fast decision rule

Ask yourself:

  • Am I talking about this object? Use self
  • Am I talking about this type? Use Self

FAQ

What does self mean in Rust?

self refers to the current instance of a type inside a method. It lets you read or modify that specific value.

What does Self mean in Rust?

Self refers to the current type inside an impl block or trait. It is often used in return types and constructors.

Is Self the same as the struct name in Rust?

Inside an impl block, yes. For example, inside impl User, Self means User.

Why does Rust use both self and Self?

Because one is for values and the other is for types. Rust keeps those ideas separate to make code clearer and safer.

When should I use Self instead of the type name?

Usually inside impl blocks and traits, especially for constructors and return types. It makes code easier to refactor.

Can I use self in a function that is not a method?

No. self is only available when it is declared as a method receiver, such as &self, &mut self, or self.

Can a method use both self and Self?

Yes.

impl Item {
    fn duplicate(&self) -> Self {
        Self {
            name: self.name.clone(),
        }
    }
}

Here self is the current value, and Self is the return type.

Take Quiz

Mini Project

Description

Create a small Rust program that models a Rectangle type. This project demonstrates both self and Self in a practical way: Self will be used to create rectangles, and self will be used to inspect and modify a specific rectangle instance.

Goal

Build a Rectangle type with methods that create, read, and update rectangle values using both Self and self correctly.

Requirements

  • Define a Rectangle struct with width and height fields.
  • Add a constructor that returns Self.
  • Add a method that calculates area using &self.
  • Add a method that resizes the rectangle using &mut self.
  • Print the rectangle area before and after resizing.
Take Quiz

Keep learning

Related questions

View more