fn xory<'a>(x: &'a str, y: &'a str) -> &'a str { x }
What is the advantage of the above code over using two lifetimes? Are there any situations in which the above code will work, but 2 lifetimes won't?
It really depends on your use case. Given the exact code you wrote:
fn xory<'a>(x: &'a str, y: &'a str) -> &'a str {
x
}
Here it is an disadvantage to use only one lifetime, because the return value only depends on the x
argument, not on the y
one. Let's imagine this user code:
let x_in = "paul".to_owned();
let out = {
let y_in = "peter".to_owned();
xory(&x_in, &y_in)
};
We would expect that this works fine, because out
is basically x_in
. But the compiler complains:
<anon>:12:22: 12:26 error: `y_in` does not live long enough
<anon>:12 xory(&x_in, &y_in)
^~~~
<anon>:13:7: 14:2 note: reference must be valid for the block suffix following statement 1 at 13:6...
<anon>:13 };
<anon>:14 }
<anon>:11:39: 13:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 11:38
<anon>:11 let y_in = "peter".to_owned();
<anon>:12 xory(&x_in, &y_in)
<anon>:13 };
This is because the compiler assumes (from the xory
signature) that the output from xory
references both arguments. So it's often better to specify lifetimes as detailed as possible to avoid unnecessary conditions/assumptions/relationships between parameters.
In some cases you need to use only one lifetime (or a slightly different solution): suppose you want to return either x
or y
depending on some condition:
fn xory<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() == 42 {
x
} else {
y
}
}
Here the lifetime of the output can depend on both arguments' lifetimes and we don't know on which one at compile time. Therefore we have to prepare for the worst and do it like this.