There are three different lifetime specifiers on an impl:
impl<\'a> Type<\'a> {
fn my_function(&self) -> &\'a u32 {
self.x
'a
is a lifetime parameter in both cases. That's a kind of generic parameter, so each use of Type
or each use of get_text
can pick a different "value" for that generic parameter. Actual lifetimes are never picked explicitly by the programmer, except when you use 'static
.
The compiler will infer what 'a
should be for each value of Type
or each use of get_text
.
impl<'a>
introduces a new lifetime parameter for the whole impl block. It is then used in the type: impl<'a> Type<'a> { .. }
Exactly what 'a
means depends on how it is used in the definition of Type
. From your example, I guess that Type
is this:
struct Type<'a> {
x: &'a u32,
}
This definition reads: For every lifetime 'a
, define Type to contain a reference x: &'a u32
. So Type
is generic and can store a reference with any lifetime.
impl<'a> Type<'a> { .. }
reads: For every lifetime 'a
, define methods for the type Type<'a>
.
Since we now know the struct definition of Type
, we know that the 'a
parameter inside the impl block is always equal to the lifetime of the reference in Type
's x field.
The one on the return type -> &'a u32 tells that the variable which is receiving the return value should not die before...before what? Before the object of type Type dies?
'a
is the lifetime of the reference stored inside a value of Type<'a>
, and it has no other relation to the Type value itself. The only rule is that 'a
must outlive the Type value itself, because it is not allowed to store a reference past its end of life. So in fact, we can hold on to that &'a u32
until at least the point when the Type
value dies, and maybe longer.
impl TextEditor {
//Other methods omitted ...
pub fn get_text<'a>(&'a self) -> &'a String {
return &self.text;
}
}
This is really common. &self
is a reference to the self value — a borrow — and the method get_text
is again a generic item. It has one generic parameter — a lifetime parameter.
It reads, for any lifetime 'a
, borrow self as the reference &'a self
(reference of that lifetime) and return a reference to String with the same lifetime.
The use of the same parameter on both the input &self
and the output &String
means that they are connected and Rust will treat self as borrowed as long as the returned reference to String is alive.
Again, the method get_text
is generic, and the compiler will pick a "value" for 'a
for each use of the method. It's a method that can return variously long borrows of a String, depending on how long you allow it to borrow self
. Sometimes it picks a long lifetime so that you can hold onto the returned &String
for a long time. Some uses of get_text
will use a shorter lifetime, if you don't use the returned value at all.
In this case, since we see that &'a String
is tied directly to a borrow &'a self
of a TextEditor
value, we know that we can only keep the String reference around at most as long as we can hold a borrow of the TextEditor
value.
Paraphrasing the Rust code:
impl<'a>
"If you give me a lifetime..." (the compiler normally supplies this based on context when using the type)
Type<'a> {
"...I'll describe how to implement Type<'a>
". So Type
probably contains references (which need a lifetime).
fn my_function(&self) -> &'a u32 {
"...and given a reference to Type<'a>
, you call my_function()
to get a reference to a u32
with lifetime 'a
." Note that the lifetime of the &self
reference is not directly tied to 'a
; it can be shorter (but usually not longer than 'a
, since a type can't outlive contained references).
In the second case:
impl TextEditor {
"Here's how to implement a non-lifetime parametric type TextEditor
..."
pub fn get_text<'a>
"Given a lifetime 'a
which you can choose (it's an input parameter)..."
(&'a self)
"...and a reference to a TextEditor
which lives for at least 'a
.."
-> &'a String {
"...you can call the get_text
method and receive a borrowed reference to a String
which lives for the same time."
In more practical terms, this really means that the String
is reborrowed directly from the TextEditor
- as long as that String
reference is alive, the &self
borrow is considered to still be active and you won't be able to take any &mut
references.