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.
selfrefers to the current value or instance of a type.Selfrefers 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:
&selfmeans the method borrows the currentUserself.nameaccesses a field on that specific instance
Self means the current type
Mental Model
Think of a class blueprint and a built object.
Selfis the blueprint name: the type itselfselfis the actual object in your hands
If you build a Car:
SelfmeansCarselfmeans a specific car, such as your blue car parked outside
So:
- use
Selfwhen talking about what kind of thing it is - use
selfwhen talking about the current thing itself
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
&selfborrows the current instance immutably&mut selfborrows the current instance mutablyselftakes ownership of the current instance
Using Self in return types and constructors
{
value: ,
}
{
() {
{ value: }
}
}
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:
struct Bookdefines a type namedBook.- Inside
impl Book,Selfrefers to the typeBook. fn new(title: String) -> Selfsays thatnewreturns a .
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 (input: &) ;
}
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:
&selffor read-only access&mut selffor modificationselfwhen 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 }
}
}
Common Mistakes
1. Thinking self and Self are interchangeable
They are not.
selfis a valueSelfis 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:
{
name: ,
}
{
() {
(, .name);
}
}
Comparisons
| Concept | Meaning | Used for | Example |
|---|---|---|---|
self | The current instance/value | Accessing fields and calling instance logic | self.name |
Self | The current type | Return types, constructors, trait definitions | fn new() -> Self |
self receiver forms
| Syntax | Meaning |
|---|---|
&self | Borrow the current instance immutably |
&mut self |
Cheat Sheet
self= the current instanceSelf= 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.nameaccesses a field on the current valueSelf { ... }constructs a value of the current type
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?
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
Rectanglestruct withwidthandheightfields. - 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.
Keep learning
Related questions
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Associated Types vs Generic Type Parameters in Rust: When to Use Each
Learn when to use associated types vs generic parameters in Rust traits, with clear rules, examples, and practical API design advice.
Can a Struct Extend Another Struct in Rust? Composition vs Inheritance
Learn how Rust handles struct reuse without inheritance, using composition, traits, and wrapper structs with practical examples.