DEV Community

pintuch
pintuch

Posted on

Rust - my dumbness with grokking impl<T>

The first time I came across code like this

impl<T> MyTrait for MyStruct<T> {...}
Enter fullscreen mode Exit fullscreen mode

I had wondered why must the generic type T show up next to both the impl as well as MyStruct. Wasn't MyStruct<T> enough to convey the intent?

I had my aha! moment today while working on a program that looked something similar to this:

struct MyStruct<T> {
    x: T    
}

trait Bogus {
    fn do_nothing(&self);
}

// missed the `impl<T>`
impl Bogus for MyStruct<T> {
    fn do_nothing(&self) {
        println!("do nothing")
    }
}

// somewhere way down in the code
type T = i32;

Enter fullscreen mode Exit fullscreen mode

Out of habit, I had missed the type parameter T next to the impl keyword. The code still managed to compile.

Later, I noticed what had happened. So, did I end up implementing the Bogus trait for the generic MyStruct<T> or was it for MyStruct<i32>? As you might have already guessed, it's the latter.

It was now so obvious that the T next to impl serves the purpose of disambiguation. The compiler can't just assume it's a generic type just because the type declaration isn't immediately in our focus.

// implement Bogus Trait for MyStruct<T> where T could be any type
impl<T> Bogus for MyStruct<T> {
    fn do_nothing(&self) {
        println!("do nothing")
    }
}

// implement Bogus Trait for MyStruct<T> where T is a type declared somewhere
impl Bogus for MyStruct<T> {
    fn do_nothing(&self) {
        println!("do nothing")
    }
}

Enter fullscreen mode Exit fullscreen mode

I feel so dumb that it took me so long to grok something so obvious!

Top comments (1)

Collapse
 
rsalmei profile image
Rogério Sampaio de Almeida

That initial <T> declaration is actually read as "For any type T...". And that's why it supports trait bounds there, an impl<T: Clone + Send> means "For any type T that also implements Clone and Send..." 😉