2

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,157
  • 1
  • 25
  • 44
Gilles
  • 23
  • 1
  • 5
  • 1
    In `items: Vec`, 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 - Krabbe mit Hüten Mar 04 '19 at 14:24

1 Answers1

6

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,566
  • 4
  • 29
  • 55
Jmb
  • 12,991
  • 20
  • 46
  • 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