我很难将其编译成:
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() {}
据我所知,生命时间是合理的,但我收到错误......
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 || {
| ^^^^^^^^^^^^^
我不明白错误所指的生命周期 - 封闭体的生命周期? - 或者为什么他们必须比静态寿命更长。
答案 0 :(得分:8)
导致此问题的生命周期约束是Thread::spawn
中的生命周期约束,它要求FnOnce
闭包为Send
。 Send
需要'static
,这意味着数据不包含非'static
数据。您的数据Foo
包含借用的str
,而不是'static
,这使得Foo
非'static
。因此,您无法跨线程发送Foo
。
这是为什么?由于Foo
包含借用,因此它仅在很短的时间内有效。如果Rust允许您将Foo
的实例发送到另一个线程,那么该线程在借用的数据变为无效之后很久就可以轻松使用Foo
。
您可能认为这实际上过于严格,而且您是对的。只要你能向借用检查器证明线程在某个生命周期内终止,就没有理由不允许本地并行。 Rust目前没有构造可以做到这一点,但是这个问题有一些未来的解决方案,例如this RFC扩展Send
特征以允许本地并行。