What’s the difference between self and Self?

Self is the type of the current object. It may appear either in a trait or an impl, but appears most often in trait where it is a stand-in for whatever type will end up implementing the trait (which is unknown when defining the trait):

trait Clone {
    fn clone(&self) -> Self;
}

If I then implement Clone:

impl Clone for MyType {
    // I can use either the concrete type (known here)
    fn clone(&self) -> MyType;

    // Or I can use Self again, it's shorter after all!
    fn clone(&self) -> Self;
}

I could also use it in a regular impl if I am lazy (it’s shorter!):

impl MySuperLongType {
    fn new(a: u32) -> Self { ... }
}

self is the name used in a trait or an impl for the first argument of a method. Using another name is possible, however there is a notable difference:

  • if using self, the function introduced is a method
  • if using any other name, the function introduced is an associated function

In Rust, there is no implicit this argument passed to a type’s methods: you have to explicitly pass the “current object” as a method parameter. This would result in:

impl MyType {
    fn doit(this: &MyType, a: u32) { ... }
}

As we have seen, as a shorter form this could also be (still verbose):

impl MyType {
    fn doit(this: &Self, a: u32) { ... }
}

Which is actually what &self boils down to under the covers.

impl MyType {
    fn doit(&self, a: u32) { ... }
}

Thus the correspondence table:

self => self: Self
&self => self: &Self
&mut self => self: &mut Self

The way to invoke those functions change, however:

impl MyType {
    fn doit(&self, a: u32) {
        // ...
    }
    fn another(this: &Self, a: u32) {
        // ...
    }
}

fn main() {
    let m = MyType;

    // Both can be used as an associated function
    MyType::doit(&m, 1);
    MyType::another(&m, 2);

    // But only `doit` can be used in method position
    m.doit(3);     // OK: `m` is automatically borrowed
    m.another(4);  // ERROR: no method named `another`
}

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)