Search code examples
rusttraits

What is self in a trait with generics?


The goal: implement a default implementation of a trait for any type which has a to_string().

So my approach might actually be completely wrong. But I am asking the question this way first because it's an interesting one nonetheless.

use core::fmt::Display

trait MyStyle<T: Display> {
  fn pretty(&self) -> String {
     let buf = self.to_string();
     // manipulate buf
     buf
  }
}

In the above code, what exactly is self? My env (through rust-analyzer) just tells me self: &Self // size = 8, align = 0x8. But what type is it?

Obivously this code doesn't work, or I wouldn't be here, because I get

the method to_string exists for reference &Self, but its trait bounds are not satisfied.

If it says to_string exists, that suggests that self could be some reference to Display, but I don't understand the rest, and why it does not compile.


Solution

  • Self in a trait refers to the type implementing that trait. Thus, in the trait definition it represents any type that implements that trait. You could think of it as a generic S where S: MyTrait<T>. It does not refer to one singular type.

    The goal: implement a default implementation of a trait for any type which has a to_string().

    This is pretty simple and you may have over complicated things by making your trait generic. This is likely what you want:

    use std::fmt::Display;
    
    trait MyStyle: Display {
        fn pretty(&self) -> String {
            let buf = self.to_string();
            // manipulate buf
            buf
        }
    }
    

    Likely with an additional impl<T> MyStyle for T where T: Display {} to actually create a blanket implementation for anything that implements Display.