Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struct lifetimes could use clarification #210

Open
timmc opened this issue Sep 23, 2024 · 2 comments
Open

Struct lifetimes could use clarification #210

timmc opened this issue Sep 23, 2024 · 2 comments

Comments

@timmc
Copy link

timmc commented Sep 23, 2024

  • I have searched open and closed issues and pull requests for duplicates, using these search terms:
    • lifetimes
    • lifetime
  • I have checked the latest main branch to see if this has already been fixed, in this file:
    • src/ch10-03-lifetime-syntax.md

URL to the section(s) of the book with this problem:

https://rust-book.cs.brown.edu/ch10-03-lifetime-syntax.html#lifetime-annotations-in-struct-definitions

Description of the problem:

While the discussion of lifetimes as they relate to functions is quite helpful, there's very little here about how structs are related to lifetimes. Don't struct instances always have to outlive their ref fields? What does it mean for a struct to have multiple lifetime annotations? What is being enforced differently if I have multiple fields with the same lifetime vs. different ones?

Suggested fix:

Broadly, it would help to have those questions answered! I'm still learning Rust, so I can't suggest authoritative answers. However, from IRC, I got the following notes that made sense to me:

  • The lifetime annotations on structs are mostly for the programmer rather than the compiler.
  • If a ref field is private, the presence of the lifetime annotation on the struct may be the only IDE-accessible documentation of how the lifetimes of params of a new method (for instance) relate to the struct's lifetimes.
@willcrichton
Copy link
Collaborator

To answer your specific questions:

Don't struct instances always have to outlive their ref fields?

The opposite, ref fields must outlive structs containing them.

What does it mean for a struct to have multiple lifetime annotations? What is being enforced differently if I have multiple fields with the same lifetime vs. different ones?

A struct can contain references that are guaranteed to live for different lengths of time. Both lengths of time are longer than the struct's lifetime, but are not necessarily equal. For example:

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

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

fn works() {
    let a = 1;
    let x = &a;
    let z = {
        let b = 2;
        let y = &b;
        let foo = Foo { x, y };
        foo.x
    };
    println!("{z}");
}

fn does_not_work() {
    let a = 1;
    let x = &a;
    let z = {
        let b = 2;
        let y = &b;
        let foo = Bar { x, y };
        foo.x
    };
    println!("{z}");
}

The first function compiles while the second one does not. They are the same except for the struct being used. In the second function, the struct Bar requires its fields have the same lifetime, so Rust conservatively picks the shorter lifetime of &b. In the first function, the struct Foo allows the fields to have different lifetimes, so Rust understands that foo.x lives as long as &a.

The lifetime annotations on structs are mostly for the programmer rather than the compiler.

The annotations are definitely also for the compiler, as shown in the example above.

Your general point about explaining this more in the book is well-taken, I'll see how to work it in.

@timmc
Copy link
Author

timmc commented Oct 1, 2024

Oops yes, I wrote that first one backwards. :-D And thanks for the example, that's helpful! Something like that would be really useful in illustrating that concept.

I think the last thing that I'm shaky on is the distinction between the lifetime parameters for the struct reference vs. the struct type. In the book we have fn foo<'a, 'b>(x: &'a ImportantExcerpt<'b>). Here, I infer that 'b is describing the lifetime of references in one or more fields of the struct, while 'a is describing the lifetime of the reference to the struct itself. Hopefully that's correct! If so, making it explicit could be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants