Hello.
My problem was to sort a Vec<String>
by a key, that is a part of that string:
fn main() {
let mut a = ["hello", "beta", "world", "alpha"].map(|s| s.to_string());
a.sort_by_key(|s| &s[..1]);
}
The code above fails to compile with the following error:
error: lifetime may not live long enough
|
26 | a.sort_by_key(|s| &s[..1]);
| -- ^^^^^^^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 str
| has type `&'1 String`
I know that I can use sort_by
instead, to avoid dealing with lifetimes, but I want to understand why I can't use sort_by_key
nevertheless.
The function sort_by_key
:
pub fn sort_by_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
// ...
}
I guess, the code fails to compile because the compiler cannot be certain that the returned value of the closure (wihch is a reference to argument &String
) won't outline the String, since F: FnMut(&T) -> K
does not specify any lifetime requirements for K. Therefore, the caller of the closure won't have any information about how long the returned value lives, possibly letting it outlive the referent.
The failure to compile is understandable, but then why can't we enforce the closure F
to only return types that live at least as long as the argument lives? It can be easily done for regular functions:
fn bar<'a>(a: &'a String) -> &'a str {
&a[..1]
}
But I don't know a way to make it work for closures, specifying the constraint in their template type, somewhat similar to this: F: FnMut(&'a) -> K + 'a
. It doesn't work, because 'a
is not defined anywhere.
Is it possible to inform the compiler that the return value of a closure lives as long as the argument lives? If not, why? Is it not implemented yet, or it is impossible to implmement without breaking rust safety guarantees?