Max_by_key provokes conflicting lifetimes

I lost a lot of time trying to figure out what the problem is with the lifetimes in the following code:

fn main() {
    let v: Vec<(String, String)> = vec![];
    v.into_iter().max_by_key(|(key, _)| key);
}
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
 --> src/main.rs:3:32
  |
3 |     v.into_iter().max_by_key(|(key, _)| key);
  |                                ^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 3:30...
 --> src/main.rs:3:30
  |
3 |     v.into_iter().max_by_key(|(key, _)| key);
  |                              ^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:3:32
  |
3 |     v.into_iter().max_by_key(|(key, _)| key);
  |                                ^^^
note: but, the lifetime must be valid for the method call at 3:5...
 --> src/main.rs:3:5
  |
3 |     v.into_iter().max_by_key(|(key, _)| key);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that a type/lifetime parameter is in scope here
 --> src/main.rs:3:5
  |
3 |     v.into_iter().max_by_key(|(key, _)| key);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

(Playground)

I found an explanation on this exact problem, however, the solutions proposed there do not work. I tried changing it to &(key, _) and *key, but it then complains about moving a value from behind a shared reference.

I've worked around this issue with the following code:

fn main() {
    let v: Vec<(String, String)> = vec![];
    v.into_iter().max_by(|a, b| a.0.cmp(&b.0));
}

What's wrong with the first example?

max_by_key doesn't allow temporary references. It needs to keep the key around for the next comparison, but the temporary reference you're getting inside the function is not guaranteed to outlive the function call.

3 Likes

I didn't think of that! Thank you for the explanation!

Is there a way to fix the code without cloning/copying?

Using max_by instead is the right solution.