I'm trying to sort a Vec<String> using a key function that returns references to the strings in the vector. A contrived example is to use the identity function as key function (which of course is useless, but it's the minimal example to reproduce my problem):
fn key(x: &String) -> &String {
x
}
fn example(items: Vec<String>) {
items.sort_by_key(key);
}
This gives the following error:
error[E0308]: mismatched types
--> src/lib.rs:6:11
|
6 | items.sort_by_key(key);
| ^^^^^^^^^^^ lifetime mismatch
|
= note: expected associated type `<for<'r> fn(&'r String) -> &'r String {key} as FnOnce<(&String,)>>::Output`
found associated type `<for<'r> fn(&'r String) -> &'r String {key} as FnOnce<(&String,)>>::Output`
= note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
I don't understand why I get this error, so I tried to track this down. I first implemented my own version of sort_by_key():
fn sort_by_key<T, K: Ord>(a: &mut [T], key: fn(&T) -> K) {
a.sort_by(|x, y| key(x).cmp(&key(y)));
}
When trying to call this function, I get what looks like the "opposite" error:
error[E0308]: mismatched types
--> src/lib.rs:6:29
|
6 | sort_by_key(&mut items, key);
| ^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r> fn(&'r String) -> &String`
found fn pointer `for<'r> fn(&'r String) -> &'r String`
I can make this code compile by fixing the key type to &T instead of using the generic parameter K, or by using &K instead of K as return type for the key function:
fn sort_by_key_v2<T: Ord>(a: &mut [T], key: fn(&T) -> &T) {
a.sort_by(|x, y| key(x).cmp(&key(y)));
}
fn sort_by_key_v3<T, K: Ord>(a: &mut [T], key: fn(&T) -> &K) {
a.sort_by(|x, y| key(x).cmp(&key(y)));
}
I also tried adding lifetime annotations, but that only shifted the error around without resolving it.
Here's the three versions of the sort_by_key() function on the Playground.
Why am I getting these errors? Is there any way to fix them while keeping the key type K completely generic?