rustlifetimedifference

What are the differences between these two function? They look the same


I am a newbie of Rust. There are two function here. When I compile, foo1 compiles pass and foo2 displays an error. But they only add an irrelevant parameter to foo1 compared to foo2, what is the reason for this?

fn main() {
    let a = 33;
    let x = foo1(&a);
    let y = foo2();
    println!("{x} {y}");
}

fn foo1(_a: &i32) -> &str {
    let x = "ddd";
    return x;
}

fn foo2() -> &str {
    let x = "ddd";
    return x;
}
➜  src git:(master) ✗ rustc -V     
rustc 1.73.0 (cc66ad468 2023-10-03)

➜  src git:(master) ✗ rustc main.rs
error[E0106]: missing lifetime specifier
  --> main.rs:13:14
   |
13 | fn foo2() -> &str {
   |              ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
   |
13 | fn foo2() -> &'static str {
   |               +++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0106`.

Solution

  • Because foo1() has a reference as parameter, by convenience the compiler assumes the returned reference has the same lifetime as the parameter (this is almost always correct in practice).
    You can see this with these slightly modified lines:

        let x_out = {
            let a = 33;
            let x_in = foo1(&a);
            x_in
        };
    

    Here, the compiler complains because x_out will outlive a.
    Of course, looking into foo1(), we can see that the result does not reference anything related to the parameter.
    The convenience is misleading here, and we should have written -> &'static str.

    In foo2(), this convenience cannot even take place because there is no reference as parameter.
    We have no choice but to explicitly express the lifetime -> &'static str.