1

I'm trying to solve the toy problem of finding the longest string in a slice, in parallel. But I ran into the following compiler error:

error[E0495]: cannot infer an appropriate lifetime for autoref due
to conflicting requirements
  --> main.rs:10:33
   |
10 |     for assigned_lines in input.chunks(max_lines_per_worker as usize) {
   |                                 ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1
defined on the body at 5:59...
  --> main.rs:5:60
   |
5  | pub fn max_length(input: &[&str], workers: usize) -> usize {
   |                                                            ^
note: ...so that reference does not outlive borrowed content
  --> main.rs:10:27
   |
10 |     for assigned_lines in input.chunks(max_lines_per_worker as usize) {
   |                           ^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@main.rs:11:36: 19:10 assigned_lines:&[&str]]` will meet its required lifetime bounds
  --> main.rs:11:22
   |
11 |         let handle = thread::spawn(move || {
   |                      ^^^^^^^^^^^^^

If I understand correctly, the compiler is complaining because it can't figure out that the threads (and thus the closed over values) should not live beyond the end of this function. I need to tell it that somehow, probably by specifying a lifetime?. I don't know what to put the lifetime specifier(s) onto, and there doesn't seem to be some kind of special 'this_function lifetime, so I'm not sure what (say) marking handles and each individual handle with the same lifetime would do to solve the problem.

Here's the code that produced the error message.

use std::thread;
use std::cmp::max;

pub fn max_length(input: &[&str], workers: usize) -> usize {
    let mut result = 0;
    let max_lines_per_worker = (input.len() as f32 / workers as f32).ceil();
    let mut handles = Vec::new();

    for assigned_lines in input.chunks(max_lines_per_worker as usize) {
        let handle = thread::spawn(move || {
            let mut count = 0;

            for line in assigned_lines {
                count = max(count, line.len())
            }

            count
        });

        handles.push(handle);
    }

    for handle in handles {
        if let Ok(count) = handle.join() {
            result = max(result, count);
        }
    }

    result
}

fn main() {
    println!("{:?}", max_length(&LINES, 3));
}

const LINES: [&'static str; 4] = ["abc", "123", "qwerty", "zxcvbnm"];
Ryan1729
  • 940
  • 7
  • 25
  • The Rust term for such a thread is a "scoped" thread. There is no way to do this in the standard library, but multiple crates provide the functionality. The linked duplicate discusses some of them. – Shepmaster Feb 13 '17 at 01:40
  • Ah, that's the phrase I should have been searching for. I managed to get a version of the above code working using [crossbeam](https://crates.io/crates/crossbeam) after a minimum of fuss. – Ryan1729 Feb 13 '17 at 03:59

0 Answers0