Lifetime annotation makes order of argument matter

Lifetime annotation does not change how long a reference lives. But it can affect how people write code. Both line 6 & 7 does not compile with the below restricted lifetime version of first2() function. But line 6 compiles with the relaxation version of the first() function, and line 7 does not compile with it.

It turns out the order of the arguments to function call matters : ) Can the language mandates restricted lifetime version by default, so the order will not matter?

Is it possible to write overloaded function based on lifetime parameter? So the two function can share the same name.

fn main() {
    let s1 = String::from("s1");
    let ret;
    {
        let s2 = String::from("s2");
        ret    = first(s1.as_str(), s2.as_str()); //line 6
        // ret = first(s2.as_str(), s1.as_str()); //line 7, Err on relaxation ver
    }
    println!("ret: {}", ret);
}

//relaxation lifetime version
//connecting some parameter references and return ref.
fn first<'a>(s1: &'a str, s2: &str) -> &'a str {
    s1
}

//restricted lifetime version,
//connecting all parameter references and return ref.
fn first2<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    s1
}

I think you misunderstand something. The two signatures are not equivalent. The first one is basically:

fn first<'a, 'b>(s1: &'a str, s2: &'b str) -> &'a str {
    s1
}

It's not the order of the arguments that matters, it's the identity of the hidden/inferred lifetime parameters.

3 Likes

Order matters for other reasons.

fn f(one: i32, two: String) {}

You may complain that's different, but types that differ by lifetime are distinct types. first takes two distinct types [1], while first2 takes one distinct type.

It can't be changed because the two examples have different semantic meaning and it would be a reduction in expressiveness. As you yourself demonstrated, it is not backwards compatible.

No, not in any way particular to lifetime parameters. (E.g. two traits can have methods with the same name, which must be unambiguated; an inherent impl method can shadow a trait method.)


  1. with the possibility of them being the same ↩ī¸Ž

3 Likes