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

血红的双手。 提交于 2021-02-06 10:05:38

问题


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?


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/39355984/what-does-the-first-explicit-lifetime-specifier-on-an-impl-mean

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!