Lifetime Issues Using Threads

It's hard for me to compile this:

use std::thread::{self, JoinHandle}; struct Foo<'c> { foo: &'c str, } impl<'c> Foo<'c> { fn use_in_another_thread<F>(self, mut cb: F) -> JoinHandle<Foo<'c>> where F: FnOnce(&mut Foo), F: Send { thread::spawn(move || { cb(&mut self); self }) } } fn main() {} 

As far as I can see, life times sound, but I get errors ...

 error[E0477]: the type `[ closure@src /main.rs:12:23: 15:10 cb:F, self:Foo<'c>]` does not fulfill the required lifetime --> src/main.rs:12:9 | 12 | thread::spawn(move || { | ^^^^^^^^^^^^^ | = note: type must outlive the static lifetime error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> src/main.rs:14:13 | 14 | self | ^^^^ | note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 11:4... --> src/main.rs:11:5 | 11 | { | _____^ starting here... 12 | | thread::spawn(move || { 13 | | cb(&mut self); 14 | | self 15 | | }) 16 | | } | |_____^ ...ending here note: ...so that expression is assignable (expected std::thread::JoinHandle<Foo<'c>>, found std::thread::JoinHandle<Foo<'_>>) --> src/main.rs:12:9 | 12 | thread::spawn(move || { | _________^ starting here... 13 | | cb(&mut self); 14 | | self 15 | | }) | |__________^ ...ending here = note: but, the lifetime must be valid for the static lifetime... note: ...so that the type `Foo<'_>` will meet its required lifetime bounds --> src/main.rs:12:9 | 12 | thread::spawn(move || { | ^^^^^^^^^^^^^ 

I don’t understand what times the errors refer to - the lifetime of the closing body? - or why they should experience a static life time.

+6
source share
1 answer

The lifespan limitation causing this problem is the value of Thread::spawn , for which closing FnOnce should be Send . Send requires 'static , which means the data does not contain non- 'static data. Your Foo data contains a borrowed str , which is not 'static , which makes Foo not 'static . As a result, you cannot send Foo through streams.

Why is this? Since Foo contains borrowing, it is valid only with a short lifetime. If Rust allowed you to send an instance of Foo to another thread, then that thread can easily use Foo long after the data that it takes has become invalid.

You might think that this is actually too restrictive, and you would be right. There is no reason not to allow local parallelism until you can prove that the thread ends within some lifetime. There are no constructs for this in Rust, but there are some future solutions to this problem, such as this RFC , which extends the Send trait to allow local parallelism.

+8
source

Source: https://habr.com/ru/post/980464/


All Articles