Lifetimes and why does this work?

I am trying to wrap my head around lifetimes. Every time I feel I understand something there comes a example that stumps me. Could someone explain to me why this code works?

struct Blah<'a> {
    hoy: &'a str
}

fn want_a_hoy<'a, 'b>(blah: &'b Blah<'a>) -> &'a str {
    blah.hoy
}

fn main()
{
    let mut b : Option<&str> = None;
    {
        let blah = Blah{hoy : "Frodo"};
        b = Some(want_a_hoy(&blah));
    }
    println!("{}", b.unwrap());
}

Here is why I believe this should not work - line where Blah is instantiated is where 'b starts and ends at the end of the scope. Given that Blah has an inner lifetime 'a it seems that 'b outlives 'a. If that were the case then println!() should fail saying that you are trying to access a reference that has outlived its lifetime. What is the fallacy here?

Thanks in advance.

You instantiate it with a string literal, which has type &'static str. That is why it works: when want_a_hoy() is called, lifetime 'static (which outlives any other lifetime) is substituted for generic lifetime variable 'a.

Here is a version of your definitions that would fail, because the Blah owns the string, and thus the string cannot outlive the Blah:

struct Blah {
    hoy: String
}

fn want_a_hoy<'b>(blah: &'b Blah) -> &'b str {
    blah.hoy.as_str()
}

It would also fail if you simply changed the return type of want_a_hoy to be -> &'b str without doing anything else, because then even though .hoy can live longer, want_a_hoy isn't actually promising that in its signature. But with the owned String, there is no longer an 'a lifetime at all.

How'd you get from "given that Blah has an inner lifetime 'a" to "'b outlives 'a"?

&'b Blah<'a> implies (imposes even) the opposite bound, 'a: 'b ('a outlives 'b).

Another fallacy I've seen is that the 'a of a Blah<'a> can't be longer that the liveness scope of the value (e.g. of the blah variable). If that were true, you couldn't do let local: &'static str = "".

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.