The first time I came across code like this
impl<T> MyTrait for MyStruct<T> {...}
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;
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")
}
}
I feel so dumb that it took me so long to grok something so obvious!
Top comments (1)
That initial
<T>
declaration is actually read as "For any type T...". And that's why it supports trait bounds there, animpl<T: Clone + Send>
means "For any type T that also implements Clone and Send..." 😉