I am a beginner of rust, nowdays I have read the content of lifetime; and I wonder that for &'a T, dose it mean the value of T having a lifetime of 'a or the Reference variable has a lifetime of 'a?
I am a beginner of rust, nowdays I have read the content of lifetime; and I wonder that for &'a T, dose it mean the value of T having a lifetime of 'a or the Reference variable has a lifetime of 'a?
Don't think of it as having a lifetime, think of it more as requiring a lifetime.
&'a T means "A reference to a type T that is guaranteed to be valid for at least 'a".
Neither T nor the variable that stores the reference 'have the lifetime 'a'. Instead, a variable is 'required to be available for at least 'a' to be referenced by that.
That's at least how my brain thinks about it, and it worked out pretty well so far.
A couple more details:
&'static T - A reference to a T that has no restrictions on how long it can be borrowed; therefore it can be stored in structs without lifetime restrictions.&'a T - A reference to a T that is temporary and has to released at some point. If you store this in a struct, that struct will carry over the lifetime T.T where T: 'static or any struct that doesn't have a lifetime annotation - An owned object that doesn't depend on anything. It doesn't borrow anything and it can be freely stored in all other structsT where T: 'a - An owned object that internally stores a reference with a lifetime. This means this object has lifetime restrictions and every other object that this gets stored in needs to be annotated with a lifetime as well, just like when storing a &'a T.To sum up, a "lifetime annotation" does not specify how long an object lives, but what other objects an object depends on. It's all part of the borrow checker.
So I now hope with this explanation that you can see why, in your original &'a T example, it isn't the T that has the lifetime 'a, nor is it the variable that stores the reference. It's the reference itself that requires the lifetime 'a. It's the way for the compiler to keep track of whether objects that depend on each other get released in the right order.
Finally, here a little example:
struct MyRefStruct<'a, T>(&'a T);
fn main() {
{
// K lives for some amount of time
let k = String::from("k");
// k_ref also lives for some amount of time.
let k_ref = MyRefStruct(&k);
// Let's do something with k_ref
println!("{}", k_ref.0);
// Here, first k_ref and then k get released.
// This means, the lifetime `'a` of `k_ref` is shorter than the lifetime of `k`,
// and everything is fine.
}
{
let create_k2_ref = || {
// K lives for the duration of this closure
let k2 = String::from("k2");
// k2_ref also lives for some amount of time.
// The lifetime 'a contains the annotation that
// MyRefStruct borrows `k2`.
let k2_ref = MyRefStruct(&k2);
// This is where the compiler complains: k2_ref gets returned.
// Its 'a lifetime annotation, however, specifies that it borrows k2,
// and returning it from this function would cause it to outlive its
// borrowed value.
k2_ref
};
let k2_ref = create_k2_ref();
println!("{}", k2_ref.0);
}
}
error[E0515]: cannot return value referencing local variable `k2`
--> src/main.rs:33:13
|
27 | let k2_ref = MyRefStruct(&k2);
| --- `k2` is borrowed here
...
33 | k2_ref
| ^^^^^^ returns a value referencing data owned by the current function
Note how specific the error message is. This is only possible due to the 'a lifetime annotation, that carries all that information.
Disclaimer: I'm quite certain that this explanation is heavily simplified and slightly inaccurate compared to how it is actually implemented in the compiler.
First of all, one thing you should know is that borrow checker by default always assigns lifetime to parameters or variables in a scope to check various rules. These lifetimes are implicit which means you don't see them, but they exist.
Coming to your question, think like you haven't specified any lifetime like 'a to type T. Then, in case of function parameters your code will look like foo: &T. This means that it is a reference of type T. What you are doing by adding 'a is denoting the lifetime of &T (read as reference of type T). Nothing changes in your code apart from the fact that you decided to label the lifetime of parameter as 'a.
In addition to this explanation, I highly recommend reading the documentation on lifetimes.