I am trying to sort a Vec<String> using a key function that returns links to strings in a vector. An invented example is to use the identity function as a key function (which, of course, is useless, but this is a minimal example to reproduce my problem):
fn key(x: &String) -> &String { x }
Now given items: Vec<String> , I would like to do
items.sort_by_key(key);
This gives the following error:
error[E0271]: type mismatch resolving 'for<'r> <fn(&std::string::String) -> &std::string::String {main::key} as std::ops::FnOnce<(&'r std::string::String,)>>::Output == _' --> src/main.rs:19:11 | 19 | items.sort_by_key(key); | ^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime | = note: concrete lifetime that was found is lifetime '_#16r
I do not understand why I am getting this error, so I tried to track this. First I 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 I try to call this function, I get what looks like the "opposite" error:
error[E0308]: mismatched types --> src/main.rs:22:29 | 22 | sort_by_key(&mut items, key); | ^^^ expected concrete lifetime, found bound lifetime parameter | = note: expected type 'fn(&std::string::String) -> _' found type 'fn(&std::string::String) -> &std::string::String {main::key}'
I can make this code compiled by setting the key type to &T instead of using the universal parameter K , or using &K instead of K as the 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 to add life time annotations, but this only shifted the error, but did not fix it.
There are three versions of the sort_by_key() function on the playground .
Why am I getting these errors? Is there a way to fix them while keeping the key type K completely universal?