1

Rust noob here reading about explicit annotation of lifetimes. I see there's lots of questions about it here, so I hope this post isn't duplicating.

For me, this answers the question why the compiler needs such annotations but does not answer why the user needs it. The example in the answer is:

struct Foo<'a> {
    x: &'a i32,
}

fn main() {
    let f : Foo;
    {
        let n = 5;  // variable that is invalid outside this block
        let y = &n;
        f = Foo { x: y };
    };
    println!("{}", f.x);
}

And I can see y goes out of scope before f, but I can't think of a case where I'd want a struct with some field that could go out of scope before the parent struct? Why would anyone need that? And by extension of that question, why not just always enforce that the fields lives as long as the parent struct?

The same question applies to functions. I can't see why I would want some function that takes some borrowed variables as an argument but the variable don't live through the entire function? The only scenario I could think of is when there's some concurrency involved.

bli00
  • 2,215
  • 2
  • 19
  • 46
  • I don't quite understand, you can't have a `Foo` with an invalid `x`, thats the whole point, neither can you have a fucntion take an argument that can go out of scope before the function returns. Your code example gets rejected by the compiler. – cafce25 Jan 28 '23 at 00:58
  • So why do I need to annotate it? Why not make it so that if a field is a reference, always check that the reference lives as long as `Foo` lives? – bli00 Jan 28 '23 at 01:01
  • *"I can't see why I would want some function that takes some borrowed variables as an argument but the variable don't live through the entire function?"* - this doesn't exist. References given to a function always live strictly longer than the scope of the function. Do you have an example that suggests differently? – kmdreko Jan 28 '23 at 01:05
  • It's true that this particular annotation is the common case, but it's also possible to have struct fields with a _longer_ lifetime, e.g., `struct Foo<'a> { x: &'a str, y: &'static str, }` In this case, it would be possible to take a `y` from a `Foo` and know that it will last forever. – djmitche Jan 28 '23 at 01:06
  • @djmitche I know it's possible but I can't think of a scenario where someone would want to explicitly take advantage of that. I guess it's possible under extreme memory limitations but it feels like an unnecessary feature? – bli00 Jan 28 '23 at 01:10

1 Answers1

1

The lifetime annotation is not for Foo but for things that use the reference, outside/after it. Take this example:

struct Foo<'a> {
    x: &'a i32,
}

fn main() {
    let n = 5;
    let z;
    {
        let f = Foo { x: &n };
        z = f.x;
    };
    println!("{}", z);
}

If Foo did not keep track of the lifetime then there would be no way for the compiler to know z is valid even after f went out of scope.

In other words the annotation is there to 'extend' the lifetime of references beyond the struct they're contained in.

bli00
  • 2,215
  • 2
  • 19
  • 46
cafce25
  • 15,907
  • 4
  • 25
  • 31
  • "If Foo did not keep track of the lifetime then there would be no way for the compiler to know z is valid even after f went out of scope." -- can't the compiler infer that `Foo.x` is still being used after `f` goes out of scope? – bli00 Jan 28 '23 at 01:26
  • Yes the compiler can track the usage and the lifetime associated with `Foo` is how it does it. – cafce25 Jan 28 '23 at 11:19