Search code examples
rust

Why doesn't a 'static function argument make something live for the entire program?


I still don't understand the behavior of 'static. In the following code, say_foo works but say_bar does not:

fn say_foo(_: &String) -> &str {
    "foo!"
}
fn say_bar(_: &'static String) -> &str {
    "bar!"
}

fn main() {
    let f = "f".to_string();
    let f2 = say_foo(&f); // ok:)
    println!("{}", f2);

    let b = "b".to_string();
    let b2 = say_bar(&b); // error:`b` does not live long enough
    println!("{}", b2);
}

Even if I pass reference to both functions, the life expectancy of the passed variable is different between say_foo and say_bar.

In the chapter about lifetimes, I found that 'static is a signal that makes a lifetime of something to live in the entire program.

But this 'static does not seem to act like that: b was released before b2 (and f).

What does 'static mean?


Solution

  • You are making a very common mistake, attempting to dictate the lifetime of a reference, however lifetimes are descriptive, not prescriptive.


    'static is the lifetime of all things that live for the entire duration of the program, for example in:

    const ID: usize = 4;
    
    fn print(i: &'static usize) { println!("{}", i); }
    
    fn main() {
        print(&ID);
    }
    

    The lifetime of ID is 'static and therefore I can pass &ID to a function expecting a &'static usize.

    If I have a variable of type usize in main:

    fn main() {
        let i = 4usize;
        print(&i);
    }
    

    the compiler will however complain that i does not live long enough because &'static usize as a parameter type is a requirement: it says that ONLY variables which live at least as long as 'static (which is the longest possible lifetime) will be accepted. And i's lifetime is shorter, so it's rejected.


    To reiterate: all things in Rust have an intrinsic lifetime, and the 'a notation is only a way of observing it not a way of modifying it.