Cannot infer an appropriate lifetime due to conflicting requirements when using threads

I've the following code. It it also available on the playground

use std::io;
use std::thread;

struct Foo<R: io::BufRead + Send + 'static> {
    input: R,
}

impl<R> Foo<R>
where
    R: io::BufRead + Send + 'static,
{
    fn new(input: R) -> Self {
        Foo { input: input }
    }

    fn start(&mut self) {
        thread::spawn(move || self.read_input());
    }

    fn read_input(&mut self) {
        loop {
            let mut line = String::new();

            if self.input.read_line(&mut line).expect("failed to read") == 0 {
                return;
            }

            println!("{}", line)
        }
    }
}

fn main() {
    let mut foo = Foo::new(io::Cursor::new("some text"));
    foo.start();
}

In this snippet I create a trait object, io::Cursor which implements io::BufRead, in the main thread. I use this trait object to construct an instance of Foo.

When I call Foo.start() I start a new thread that operatos io::BufRead trait object.

This code fails to compile with:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:17:23
   |
17 |         thread::spawn(move || self.read_input());
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 16:5...
  --> src/main.rs:16:5
   |
16 | /     fn start(&mut self) {
17 | |         thread::spawn(move || self.read_input());
18 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &mut Foo<R>
              found &mut Foo<R>
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:17:23: 17:48 self:&mut Foo<R>]` will meet its required lifetime bounds
  --> src/main.rs:17:9
   |
17 |         thread::spawn(move || self.read_input());
   |         ^^^^^^^^^^^^^

error: aborting due to previous error

error: Could not compile `problem`.

Although I understand why it fails, I don't know how to fix it.

Can somebody help me with this? The lifetime of io::BufRead can be static, I need at for the whole lifetime of my program.

If you make start take self by value, you can move Foo into the new thread:

fn start(self) {
    thread::spawn(move || self.read_input());
}

Of course then you wont be able to access it while it's there, but since read_input borrows it mutably, it's locked from any other access anyway.

Thanks for your quick answer. But I'm afraid it doesn't work for in my case. I forgot to mention in my opening post that I need to use self after I spawned the thread. That is not possible with your suggestion because read_input() takes ownership. Therefore further use of self fails with 'use after move'

Here an the updated code. Also available on the playground

use std::io;
use std::thread;

struct Foo<R: io::BufRead + Send + 'static> {
    input: R,
}

impl<R> Foo<R>
where
    R: io::BufRead + Send + 'static,
{
    fn new(input: R) -> Self {
        Foo { input: input }
    }

    fn start(self) {
        thread::spawn(move || self.read_input());
        
        // do something else with `self`.
        self;
    }

    fn read_input(mut self) {
        loop {
            let mut line = String::new();

            if self.input.read_line(&mut line).expect("failed to read") == 0 {
                return;
            }

            println!("{}", line)
        }
    }
}

fn main() {
    let foo = Foo::new(io::Cursor::new("some text"));
    foo.start();
}

Do you have another suggestion?

You can use an Arc to share things between threads, but this disallows unsynchronized modification of the object for safety reasons. To be able to modify it while it's in the Arc, you can use a Mutex which allows you to lock access, such that only one thread has access at a time.

A different approach may be to use scopes from crossbeam, but these are limited by the fact that you need to wait for the threads to finish before you can exit the scope produced by the scope function. Note that scoped threads would also require a mutex to allow mutable access to the same parts of the same object from several threads.

Thanks for the suggestions. I will try them.

After some playing around I realize I need to redesign my program.

I try to share a reference to self inside a thread. And that is just not possible.

This answer on SO made me realize that.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.