参数类型的存活时间可能不够长(使用线程) [英] Parameter type may not live long enough (with threads)

查看:32
本文介绍了参数类型的存活时间可能不够长(使用线程)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这类似于参数类型可能活得不够长?,但我对解决方案的解释似乎不起作用.我原来的简化测试用例是:

This is similar to Parameter type may not live long enough?, but my interpretation of the solution doesn't seem to be working. My original boiled-down test case is:

use std::fmt::Debug;
use std::thread;

trait HasFeet: Debug + Send + Sync + Clone {}

#[derive(Debug, Clone)]
struct Person;

impl HasFeet for Person {}

#[derive(Debug, Copy, Clone)]
struct Cordwainer<A: HasFeet> {
    shoes_for: A,
}

impl<A: HasFeet> Cordwainer<A> {
    fn make_shoes(&self) {
        let cloned = self.shoes_for.clone();
        thread::spawn(move || {
            println!("making shoes for = {:?}", cloned);
        });
    }
}

这给了我错误:

error[E0310]: the parameter type `A` may not live long enough
  --> src/main.rs:19:9
   |
16 | impl<A: HasFeet> Cordwainer<A> {
   |      -- help: consider adding an explicit lifetime bound `A: 'static`...
...
19 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^
   |
note: ...so that the type `[closure@src/main.rs:19:23: 21:10 cloned:A]` will meet its required lifetime bounds
  --> src/main.rs:19:9
   |
19 |         thread::spawn(move || {
   |         ^^^^^^^^^^^^^

我没有让 A 'static,而是通过并为 HasFeet trait 添加一个明确的生命周期:

Instead of making A 'static, I go through and add an explicit lifetime to the HasFeet trait:

use std::fmt::Debug;
use std::thread;

trait HasFeet<'a>: 'a + Send + Sync + Debug {}

#[derive(Debug, Copy, Clone)]
struct Person;

impl<'a> HasFeet<'a> for Person {}

struct Cordwainer<'a, A: HasFeet<'a>> {
    shoes_for: A,
}

impl<'a, A: HasFeet<'a>> Cordwainer<'a, A> {
    fn make_shoes(&self) {
        let cloned = self.shoes_for.clone();
        thread::spawn(move || {
            println!("making shoes for = {:?}", cloned);
        })
    }
}

这现在给了我错误:

error[E0392]: parameter `'a` is never used
  --> src/main.rs:11:19
   |
11 | struct Cordwainer<'a, A: HasFeet<'a>> {
   |                   ^^ unused type parameter
   |
   = help: consider removing `'a` or using a marker such as `std::marker::PhantomData`

我认为 'a 被用作 HasFeet 特性的生命周期参数.我在这里做错了什么?

I think that 'a is used as the lifetime parameter to the HasFeet trait. What am I doing wrong here?

推荐答案

std::thread::spawn() 函数声明为在其闭包上绑定了 Send + 'static .此闭包捕获的任何内容都必须满足 Send + 'static 边界.在安全的 Rust 中, 没有办法解决这个问题.如果要使用该函数向其他线程传递数据,必须是'static,句点.

The std::thread::spawn() function is declared with a Send + 'static bound on its closure. Anything which this closure captures must satisfy the Send + 'static bound. There is no way around this in safe Rust. If you want to pass data to other threads using this function, it must be 'static, period.

可以使用适当的 API 解除 'static 限制,请参阅 如何通过将堆栈变量引用到线程? 举个例子.

It is possible to lift the 'static restriction with the proper API, see How can I pass a reference to a stack variable to a thread? for an example.

然而,'static 边界并不像看起来那么可怕.首先,你不能强制做任何有生命周期限制的事情(你不能强制做任何有限制的事情).边界只是限制可用于有界类型参数的类型集,仅此而已;如果你试图传递一个类型不满足这些界限的值,编译器将无法编译你的程序,它不会神奇地使这些值活得更久".

However, a 'static bound is not as scary as it may seem. First of all, you cannot force anything to do anything with lifetime bounds (you can't force anything to do anything with any kind of bounds). Bounds just limit the set of types which can be used for the bounded type parameter and that is all; if you tried to pass a value whose type does not satisfy these bounds, the compiler will fail to compile your program, it won't magically make the values "live longer".

此外,'static 绑定并不意味着该值必须在程序的持续时间内有效;这意味着该值不得包含生命周期不同于 'static 的借用引用.换句话说,它是值内可能引用的下限;如果没有引用,则边界无关紧要.例如,StringVeci32 满足 'static 边界.

Moreover, a 'static bound does not mean that the value must live for the duration of the program; it means that the value must not contain borrowed references with lifetimes other than 'static. In other words, it is a lower bound for possible references inside the value; if there are no references, then the bound does not matter. For example, String or Vec<u64> or i32 satisfy the 'static bound.

'static 是对 spawn() 施加的一个非常自然的限制.如果它不存在,则传输到另一个线程的值可能包含对父线程堆栈帧的引用.如果父线程在派生线程之前完成,这些引用将变为悬空.

'static is a very natural restriction to put on spawn(). If it weren't present, the values transferred to another thread could contain references to the stack frame of the parent thread. If the parent thread finishes before the spawned thread, these references would become dangling.

这篇关于参数类型的存活时间可能不够长(使用线程)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆