Lifetime specifiers inside of <Option>


#1

I’m trying to created “nested contexts” that work like prototype inheritance: if a value can’t be found in the child, it will be looked up in the parent. Therefore I have a struct that looks like this:

struct LookupContext<'a> {
    parent: Option<&'a LookupContext>,
    values: HashMap<String, i32>,
}

However, Rust complains:

4 |     parent: Option<&'a LookupContext>,
  |                        ^^^^^^^^^^^^^ expected lifetime parameter

Is this a syntax error, or am I missing something fundamental? (I saw somebody mention boxing…)

Here’s the full example:

https://play.rust-lang.org/?gist=24b4f5fa945d291c95f82079221e1896&version=stable&backtrace=0


#2

You also need to specify lifetime of struct, in addition to lifetime of a reference.

parent: Option<&'a LookupContext<'a>>,

#3

Awesome, that works! I haven’t seen this nested lifetime syntax before, any docs / examples of this in the wild?

I fixed the rest of the errors, here’s the finished example:

https://play.rust-lang.org/?gist=8cebd33976c9b46e5f8c73596988d7c0&version=stable&backtrace=0


#4

Essentially, lifetime in LookupContext<'a> is the exact same as in declaration of a struct. Because you said:

struct LookupContext<'a> {

You also needed to say this later on.

name: LookupContext<'some_lifetime>,

The same applies to generic types too, for instance.

struct HashMap<K, V> {

Requires you to say for instance this.

map: HashMap<String, i32>,

Note that Rust can get rid of lifetimes in specific situations in function declarations, but that only applies to function declarations (not structs). For instance, instead of writing this.

fn something<'a>(name: &'a str) -> &'a str {

You can write this.

fn something(name: &str) -> &str {

This works when:

  • there are no types with lifetimes on output side
  • there is a single type which requires lifetime on input side (then it’s used for all outputs)
  • there is &self or &mut self argument (then its lifetime is used for all outputs)

#5

Great! I got confused because I haven’t written many explicit lifetime specifiers. Thanks!