Impact of sloppy reference lifetimes

Hi there!

I'm very new to Rust and coming from a higher level language (Java). I would like to know what the consequences of sloppy lifetime usage are. I caught myself not really thinking about
lifetimes and instead just trying to get them to work. Of course I was not always using 'static lifetimes,
but I'm pretty sure that there are parts in my code now, where the lifetimes could be improved by a lot.

Best regards,
Dominik

If it compiles you will be fine. Could you provide an example of such a piece of code, where you think the lifetimes can be improved?

(You could try to run clippy over your code to see where your code could be improved)

1 Like

I'm not really sure where my lifetimes could be improved. It was an assumption that they could be wrong. But thanks for the clippy tip! I'll have a look at it. :smile:

I'm not sure I understand your question.

My take on lifetimes is:

  1. If you have them wrong, your program will not compile. As such it's impossible to have sloppy lifetimes.

  2. Lifetimes are not just those tick marks you put in your code. The actual lifetime of objects in your program is determined by where your data is created, how it is passed around and so on. The structure of your code defines the lifetimes of objects.

I consider myself to be new to Rust, having only started out a year ago. There are many areas of Rust I have not even looked at yet much. But I don't think I have ever written a lifetime annotation into my code. Despite that I have code that has been running in production for much of this last year.

In fact I would go as far as to say that for a lot of application level code if one starts to feel the need for lifetime annotations it's time to step back and think about your program structure and how it can be rearranged to avoid that.

I guess the view I express there likely does not apply if you are creating lower level libraries.

By the way, I'm not sure I would agree that Java is a higher level language. Given the things that one cannot do in Java that seems unlikely.

1 Like

Thanks for your answer!

Let’s say I define multiple lifetimes e. g a lifetime in an impl block and the one of a function (only an example, I guess there are other cases too). Doesn’t that affect the amount of time the target of the reference is in ram?

It is definitely possible to have sloppy lifetimes if you're writing a library, often you will accidentally use a stricter lifetime than necessary.

But don't worry about it now, if this actually causes a problem for someone they should open an issue, and you can always review your code later once you understand lifetimes better.

4 Likes

If you're coming from Java, then you're likely going to be overusing temporary borrows (only these have lifetimes to speak of) and cross-object relationships a lot.

  • Java's Objects are Arc<Mutex<Object>> in Rust. Java's GC handles what Rust needs to do with these wrapper types. Referencing objects in Java is not equivalent to & in Rust. Rust's borrows are stricter, shorter-lived and much more narrower in use.

  • Don't try using references in structs. Do use references is function arguments.

  • Don't try to make parent-child relationships, or hold on to objects just in case you'll need them. It's better to take what you need as arguments. Long-term references to objects in Rust have high cost in complexity.

  • 'static is a lifetime of string literals and leaked memory. You can't program much with these two, so it's rarely seen in real-world code. If compiler tells you it wants 'static interpret this as "references are forbidden here, use Arc".

  • In Rust getters and setters make borrow checker much stricter. Don't encapsulate just in case. If you can expose plain struct fields, do that. If you'll ever need to turn them into non-trivial getters/setters, you can use semver to break the interface.

2 Likes

No. That was my point. The actual lifetimes of objects in your code is determined by when they are created and when they are destroyed. Something created in main may live for the entire run time of your program. Something created in a function called from main may only live for the lifetime of that function. (Let's ignore reference counting pointers and such for now). No amount of lifetime tick marks can change that. Only reorganizing your code and how data flows around it can.

Let me make an analogy:

Say I have a pizza restaurant and you win a token for a free pizza at my restaurant that is valid for one month. So you have a token that references my pizza and has a lifetime of one month.

After one week you turn up to get your pizza. Sadly my business has gone bankrupt and there is no pizza restaurant. Your token is now worthless, there is no pizza, despite the lifetime the token claims it to have.

Somebody correct me if I am wrong or that is a really bad analogy.

1 Like

No. Lifetime annotations don't actively do anything at runtime. Theye are only used by the compiler to verify (or refute) the correctness of the program with regards to memory safety.

3 Likes

Lifetime parameters are just like type parameters: they do nothing, they are used by the compiler to check that the caller fulfills a contract to reject invalid code, but the generated machine code doesn't care about them at all.

1 Like