Thank you so much to both, you really helped me! I also found two relevant excerpts from the book that explained it (and gave me the ha-ha moment):
- reading the chapter about lifetimes, I realised this is not a special syntax for lifetimes, it's the same syntax used for generics, because when we write
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
we are meaning (emphasis added)
for some lifetime 'a
, the function takes two parameters, both of which are string slices that live at least as long as lifetime 'a
so we are actually declaring a generic lifetime variable, that will later be substituted automatically by the compiler:
the concrete lifetime that is substituted for 'a
is the part of the scope of x
that overlaps with the scope of y
It thus make sense to use the lifetime annotations in the same position of generic.
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
Note that we have to declare T
just after impl
so we can use T
to specify that we’re implementing methods on the type Point<T>
. By declaring T
as a generic type after impl
, Rust can identify that the type in the angle brackets in Point
is a generic type rather than a concrete type. We could have chosen a different name for this generic parameter than the generic parameter declared in the struct definition, but using the same name is conventional. Methods written within an impl
that declares the generic type will be defined on any instance of the type, no matter what concrete type ends up substituting for the generic type.
I think this explains it well, and by the way, IIUC is what allows us to also specialize the trait like impl Point<i32> { }
. And as you both said, in this latter case the generic is after the symbol because it is referred to the struct, not the impl
block, and it's being used, not declared. Whereas, in the case impl<T> Point<T>
, it is first declared, then used (even if, being it a variable, it is not substituted by a concrete type, and it stays a generic)