特质界限不满足

Mai*_*ein 5 rust

协程

这是我要调用的函数:

#[inline]
pub fn spawn<F>(f: F) -> Handle
    where F: FnOnce(&mut Coroutine) + Send + 'static
{
    Self::spawn_opts_impl(Box::new(f), Options::default())
}
Run Code Online (Sandbox Code Playgroud)

然后,我创建了一个枚举,因为我实际上是想将其从一个线程发送到另一个线程,这也是为什么要将函数装箱。我还匹配了特征约束。

enum Message {
    Task(Box<FnOnce(&mut Coroutine) + Send + 'static>),
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试从中提取函数Message

fn main(){
    let m = Message::Task(Box::new(|me| {
    }));
    let c = match m{
        Message::Task(f) => Coroutine::spawn(f)
    };
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

#[inline]
pub fn spawn<F>(f: F) -> Handle
    where F: FnOnce(&mut Coroutine) + Send + 'static
{
    Self::spawn_opts_impl(Box::new(f), Options::default())
}
Run Code Online (Sandbox Code Playgroud)

我不知道Rust在这里想告诉我什么。我认为问题是spawn期望使用非盒装函数,但是如果我尝试取消对盒装函数的引用,则会遇到相同的错误。

请注意,在问这个问题时,coroutine-rs没有建立,并且我修复了这个fork中的错误。

Fra*_*gné 5

让我们仔细阅读错误消息:

src/main.rs:168:29: 168:45 error: the trait bound
    `for<'r>
         Box<
             for<'r> std::ops::FnOnce(
                 &'r mut coroutine::asymmetric::Coroutine
             ) + Send
         >:
     std::ops::FnOnce<
         (
             &'r mut coroutine::asymmetric::Coroutine,
         )>` is not satisfied [E0277]
Run Code Online (Sandbox Code Playgroud)

基本上,您尝试将a传递Box<FnOnce>给期望实现类型的函数FnOnce

但是,您不能调用内的函数Box<FnOnce>,因为要调用它,您需要self按值传递,这意味着您需要取消引用Box,但是会产生未定大小的类型,无法按值传递(如1.9版)。

当前的解决方法是使用不稳定FnBox特征而不是FnOnceFnBox对实现的所有类型自动实现FnOnce。这是我们如何使用它:

#![feature(fnbox)]

use std::boxed::FnBox;

enum Message {
    Task(Box<FnBox(&mut Coroutine) + Send + 'static>),
}

fn main() {
    let m = Message::Task(Box::new(|me: &mut Coroutine| {
    }));
    let c = match m {
        Message::Task(f) => Coroutine::spawn(|me| f.call_box((me,)))
    };
}
Run Code Online (Sandbox Code Playgroud)

请注意,对的调用会Command::spawn收到一个调用的闭包FnBox,因为由于上述原因,我们无法将传递FnBoxCommand::spawn。另外,我必须在第一个闭包上显式注释参数类型,否则编译器会抱怨(expected concrete lifetime, found bound lifetime parameter,我认为这是编译器中的错误)。