Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the first explicit lifetime specifier on an impl mean?

Tags:

rust

lifetime

There are three different lifetime specifiers on an impl:

impl<'a> Type<'a> {
    fn my_function(&self) -> &'a u32 {
        self.x
    }
}

Type<'a> states that there is a lifetime in this impl declaration. The one on the return type -> &'a u32 states that the variable that receives the return value should not die before...before what? Before the object of type Type dies?

What's the difference to this:

impl TextEditor {
    //Other methods omitted ...

    pub fn get_text<'a>(&'a self) -> &'a String {
        return &self.text;
    }
}

Here it says for the return type to not die before the lifetime of &'a self ends.

Does the last one declare only a lifetime to this one method and the other one declares a lifetime to every method (and associate function?) in the impl declaration?

like image 943
xetra11 Avatar asked Sep 06 '16 18:09

xetra11


1 Answers

'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.

like image 140
bluss Avatar answered Oct 28 '22 16:10

bluss