简体   繁体   中英

The trait bound is not satisfied

Coroutine-rs

This is the function I am trying to call:

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

I then created an enum because I actually want to send it from one thread to another, which is also why I have boxed the function. I have also matched the trait constraints.

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

But if I try to extract the function from a Message :

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

I get the following error:

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]
src/main.rs:168         Message::Task(f) => Coroutine::spawn(f)
                                            ^~~~~~~~~~~~~~~~
src/main.rs:168:29: 168:45 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:168:29: 168:45 help: the following implementations were found:
src/main.rs:168:29: 168:45 help:   <Box<std::boxed::FnBox<A, Output=R> + 'a> as std::ops::FnOnce<A>>
src/main.rs:168:29: 168:45 help:   <Box<std::boxed::FnBox<A, Output=R> + Send + 'a> as std::ops::FnOnce<A>>
src/main.rs:168:29: 168:45 note: required by `coroutine::asymmetric::Coroutine::spawn`

I have no idea what Rust is trying to tell me here. I assume that the problem is that spawn expects a non boxed function, but I get the same error if I try to deref the boxed function.

Note that at the time this question was asked, coroutine-rs doesn't build, and I fixed the errors in this fork .

Let's read the error message carefully:

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]

Basically, you are trying to pass a Box<FnOnce> to a function that expects a type that implements FnOnce .

However, you cannot call a function that is in a Box<FnOnce> , because in order to call it, you need to pass self by value, which means that you need to dereference the Box , but that yields an unsized type, which cannot be passed by value (as of Rust 1.9).

The current workaround is to use the unstable FnBox trait instead of FnOnce . FnBox is automatically implemented for all types that implement FnOnce . Here's how we can use it:

#![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,)))
    };
}

Note that the call to Command::spawn receives a closure that calls the FnBox , because we can't pass the FnBox directly to Command::spawn for the reasons mentioned above. Also, I had to explicitly annotate the argument type on the first closure, otherwise the compiler complained ( expected concrete lifetime, found bound lifetime parameter , which I think is a bug in the compiler).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM