在Rust中,是否有一种方法可以将结构体/类型更改为“Send”?

4
我曾多次遇到这样的问题,即尝试将东西传递给 spawn 函数(创建新线程/任务),却被编译器告知 error: cannot capture variable of type "blah blah", which does not fulfill "Send", in a bounded closure有没有一种方法可以使类型满足 "Send" 的要求,还是它们已经固定在某些规则上了? 例如,我可以轻松地通过使用类似以下指令来实现 ToStr trait:
#[deriving(ToStr, Rand)]
struct Point {
    x: int,
    y: int,
}

我能否为Send特质做类似的事情呢?还是说“种类”特质被处理得不同呢?

这里有一个具体的例子,有没有什么办法可以克服这个问题呢?

fn create_process_options(cmdinfo: &CmdInfo) -> (ProcessOptions, Option<FileDesc>) {
// ... omitted
}

// "po" is of type std::run::ProcessOptions
let (po, filedesc_opt) = create_process_options(&cmdinfo);
spawn(proc() {
    let mut ps = Process::new(cmdinfo.program, cmdinfo.args, po).expect("darn");
    ps.finish();
});

编译器错误:

error: cannot capture variable of type `std::run::ProcessOptions<>`, which does not fulfill `Send`, in a bounded closure
let mut process = Process::new(cmdinfo.program, cmdinfo.args, po).expect("darn");
                                                              ^~
note: this closure's environment must satisfy `Send`
let mut process = Process::new(cmdinfo.program, cmdinfo.args, po).expect("darn");

3
这是因为ProcessOptions<'a>结构体中的dir: Option<&'a Path>字段。包含引用的结构体不能被标记为Send。剩下的问题是为什么是&Path而不是Path。答案似乎是std::io::process::ProcessConfig主要使用引用,包括cwd: Option<&str>,它可能来自于ProcessOptions.dir - Chris Morgan
1
好的。谢谢解释。我能理解为什么要设置这些限制,但在尝试进行多线程/任务编程时确实会成为一个雷区。 - quux00
1
@quux00:实际上,我认为在C++中这将是一个地雷(因为它有时会在你的脸上爆炸),而在Rust中,你只会得到一个严厉的拒绝继续。 - Matthieu M.
1个回答

8

Send是Rust的一种类型类别,而你提到的其他内容则是特性。虽然两者都可以用于限定泛型,但它们实际上有很大的不同。你必须选择一个特性,但一个类型的类别是基于其内容推断出来的 - 除了更改内容,你无法更改类型的类别。

对于大多数类型类别而言,规则是:“如果类型X的所有成员都是类型类别Y,则类型X属于类型类别Y。”

在这种情况下,由于要成为Send需要满足'static,也就是说,它们不包含任何非'static引用。由于ProcessOptions包含具有非静态生命周期Option<&'a Path>,正如Chris Morgan在他的评论中详细说明的那样,ProcessOptions不能满足Send。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接