3

I'm learning Rust with the official book. I've come across a weird syntax in my program:

pub struct Shelf<'a> {
    items: Vec<&'a Item<'a>>, // => working as expected
    //items: Vec<Item<'a>>, // => not working
    //items: Vec<&'a Item>, // => not working
}

Item is a struct that contains references to other types too:

pub struct Item<'a> {
    owner: &'a Owner,
    name: String,
    avg_rating: u32,
    status: ItemStatus,
}

pub struct Owner {
    pub name: String,
}

It seems to me that the syntax items: Vec<&'a Item<'a>> is weird and I don't think I'm doing right... What I want is a Vec that contains references to Items, and that Vec is valid as long as the references to Items it contains are themselves valid. Shouldn't it be items: Vec<&'a Item> instead?

turbulencetoo
  • 3,447
  • 1
  • 27
  • 50
Gilles
  • 33
  • 2
  • 5
  • 1
    In `items: Vec<&'a Item>`, you are not specifying the lifetime parameter `'a` in `Item`. The compiler won't be making any assumptions here, so you still need to specify it. Relevant questions: https://stackoverflow.com/q/31609137/1233251 and https://stackoverflow.com/q/43712228/1233251 – E_net4 Mar 04 '19 at 14:24

1 Answers1

9

There are two lifetimes that you need to specify:

  • Your vector contains reference to items.
  • Each item contains a reference to its owner.

You need to specify how long each type of reference lives. If you write Vec<&'a Item<'b>>, the first lifetime ('a) specifies how long references to items live, and the second lifetime ('b) specifies how long the references to owners live.

When you write Vec<Item<'a>>, the compiler doesn't know how long the items live.

When you write Vec<&'a Item>, the compiler doesn't know how long the owners live.

When you use the same lifetime for both spots (Vec<&'a Item<'a>>), you are telling the compiler that both lifetimes are the same, which means that items must live exactly as long as their owners. This may be overly restrictive, depending on your use case it might be better to tell the compiler that items may not live longer than their owners:

pub struct Shelf<'a, 'b: 'a> {
    items: Vec<&'b Item<'a>>,
}
Bruno Rijsman
  • 3,715
  • 4
  • 31
  • 61
Jmb
  • 18,893
  • 2
  • 28
  • 55
  • Thanks, that's helping a lot ! It's also highlighting that holdings refs in "container" struct is a bad idea, I should organize my code to own the things in my structs directly, not refs. So, in my example, I should reverse the logic that "Item" contains a ref to "Owner", instead I should make my struct "Owner" like this : `pub struct Owner { pub name: String, pub items: Vec, }` And avoid all the lifetimes complexity. – Gilles Mar 05 '19 at 07:44
  • Can I also ask why I need a lifetime for struct that contains Vec? Vec owns all objects of Something type (they are not references), and the struct owns Vec, so there should be no problem with lifetimes. Still it requires an explicit lifetime for Something. – Andrei Nikolaenko Apr 02 '23 at 09:04
  • @AndreiNikolaenko you will need to ask a new question with your actual code. This question is about vectors of references, if you don't have references, you shouldn't need to specify a lifetime. If the compiler still wants one, then it's a different question. – Jmb Apr 02 '23 at 09:38
  • @Jmb thank you, it seems you have already answered my question. My Vec does not store references to Something, but Something has references in it, when I remove them, the lifetime is not needed. – Andrei Nikolaenko Apr 02 '23 at 09:48