Creating a list of products, help with life times.. am I doing it wrong?


Hi Again

Sorry for asking stupid questions, but I’d like to know if this is okay code.
It compiles, but doesn’t feel right…

Playpen link

struct Product<'a> {
    product_name: &'a str,
    units_in_stock: i32,

fn get_product_list<'a>() -> Vec<Product<'a>> {
    let p1 = Product { product_name: "Gumbo Mix", units_in_stock: 1 };
    let p2 = Product { product_name: "Alice Mutton", units_in_stock: 2 };
    let p3 = Product { product_name: "Thüringer Rostbratwurst", units_in_stock: 10 };
    let p4 = Product { product_name: "Gorgonzola Telino", units_in_stock: 0 };
    let p5 = Product { product_name: "Perth Pasties", units_in_stock: 0 };
    return vec![p1, p2, p3, p4, p5];

fn main() {
    let products: Vec<Product> = get_product_list();
    println!("{:?}", products)


It’s not wrong, but it’s not really right, either. Let’s simplify a little; given:

fn f<'a>() -> &'a str {
    "Beef Pie"

What this actually means is that the function will return a &'a str for any lifetime 'a, as specified by the caller. This lifetime will also be completely independent of the data being generated. In normal circumstances, this is almost certainly not what you actually wanted.

Now, it works in this case because the type of "Beef Pie" is &'static str; that is, it is a borrowed pointer to string data which is valid for the entire lifetime of the program; that, it is also valid for any other lifetime you happen to need.

There are four things, one of which might be what you actually want:

  1. you should use String instead of &str: this means each Product will own the string data it contains.
  2. you should use &'static str instead of &'a str: this means each Product must contain a reference to static string data (i.e. a string literal, as opposed to a runtime-constructed value).
  3. there should be an argument passed to get_product_list of type &'a Something: that is, introduce an explicit link between a thing the caller has and how long the results need to live.
  4. you should return Vec<Product<'static>>: you’re returning string literals, so you might as well use the broadest lifetime possible.