Lifetime(a) = lifetime(b) iff (a=b)?

As I understand it,

  1. each "let" introduces a new scope.
  2. therefore, no variable can have the same lifetime as any other variable other than it self.

Is this true? Or is this the wrong way to think about things? If it is true, various sentences in 10.3 of the 2nd edition of the rust book seem to be incorrect. E.g.,

"The constraint we want to tell Rust about for the references in the parameters and the return value is that they all must have the same lifetime,"

Thanks!

Firstly, 2. isn't strictly true, because a) variables can be 'static, and that's really "the same for all", and b) let can bind more than one variable in one statement, and those will also share a lifetime.

Otoh, most of the times, this doesn't matter, and you're basically right. You're looking very closely though, and that's probably not appropriate for an introductory text such as the book. The right way to read it (in my words, as far as I understand it) is this: The signature fn longest<'a>(x: &'a str, y: &'a str) -> &'a str expresses the following:

Every lifetime 'a that's a lower bound for the lifetime of x AND y (that is, both x and y live for the whole duration 'a) is also a lower bound for the lifetime of the returned reference of longest.

Or, the returned reference is valid as long as both of x and y are.

3 Likes

Fair point about 'static! Heap too, perhaps?

lower bound = intersection x's and y's lifetime/scope?

It's easier for me, as a rust tourist, to think of this case as:
(1) the lifetime annotation 'a puts all parameters that share it into an equivalence class L.
(2) if the return reference is tagged w/ 'a, this implies that the lifetime of any parameter in L is >= the lifetime of the location used to store the function's result reference. (I.e., we want to guarantee a reference can't refer to something that dies before it does.)

Not sure if this is equivalent. At least for me, a little more explicitness in 10.3 as to how lifetime annotations are checked would help understand what, exactly, a lifetime annotation means. But, perhaps this is just a personal problem.

No, it doesn't have anything to do with heap-vs-stack, if that's what you mean.

That would be the greatest lower bound, and just one possibility for 'a. Of course, somewhat the one that matters the most, granted.

Sounds correct.

At least for me, a little more explicitness ...

There's just no one-size-fits-all. I, too, would have gotten into it better if it was very exact, maybe even with a formal definition or something, even if that meant tough reading upfront. But I'm pretty sure that would not have been optimal for most other people.

2 Likes

Hi! Thanks for your demonstration of two situation of same lifetime.

Recently I found a situation in which two references of different variables share same lifetime and that makes me confused.

        let mut x2: u8 = 1;
        {
            let mut x = 42;
            let mut y = &x;
            let mut yt: InvariantLifetime;
            yt = get_lifetime(&mut y);

            let mut y2 = &x2;
            let mut y2t: InvariantLifetime;
            y2t = get_lifetime(&mut y2);
            y2t = yt;
        }

These code could be compiled, which imply that yt and y2t carry same lifetime.
In above code, some type and function is implemented as(ref):

pub struct Invariant<T>(PhantomData<*mut T>);
pub struct InvariantLifetime<'id>(Invariant<&'id ()>);
fn get_lifetime<'a, T>(_: &mut &'a T) -> InvariantLifetime<'a> { InvariantLifetime::new() }

Does these code shows that two references(yt,y2t) have save timelife?