`for <'r,'r,'r> ...`不能安全地在线程之间发送

rap*_*2-h 3 rust hyper

我学习了Rust,我尝试构建一个基于hyper的微路由系统(它仅用于学习目的,我知道框架存在).

我不知道如何与一个"复杂"类型共享hyper::server::Handler.我读了错误信息,但不幸的是,我不明白如何解决它(大多数时候,生锈编译器只是说要解决什么,现在我不确定理解).

这是我尝试过的(非)工作过度简化示例:

extern crate hyper;
use std::sync::Mutex;

use hyper::*;

type Route = (method::Method, String, Box<Fn(server::Request, server::Response)>);

struct MyHandler {
    routes: Mutex<Vec<Route>>
}

impl server::Handler for MyHandler {
    fn handle(&self, req: server::Request, mut res: server::Response) {
        // This is not important
    }
}

fn main() {
    // This is not important
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error: the trait bound `for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static: std::marker::Send` is not satisfied [--explain E0277]
  --> src/main.rs:12:10
   |>
12 |>     impl server::Handler for MyHandler {
   |>          ^^^^^^^^^^^^^^^
note: `for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static` cannot be sent between threads safely
note: required because it appears within the type `Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>`
note: required because it appears within the type `(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)`
note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)>`
note: required because it appears within the type `alloc::raw_vec::RawVec<(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)>`
note: required because it appears within the type `std::vec::Vec<(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)>`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<std::vec::Vec<(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)>>`
note: required because it appears within the type `MyHandler`
note: required by `hyper::server::Handler`
Run Code Online (Sandbox Code Playgroud)

如果我使用一个简单的整数,但它不适用于Route类型,它可以工作.

因此,该特征存在问题,并且"无法安全地在线程之间发送".阅读hyper文档,我添加了一个Mutex,但我必须愚蠢,我不知道我在做什么,不知道我是不是应该停止学习Rust,或继续尝试.

Chr*_*son 6

你快到了.

错误是说MyHandler没有实现Send特征,这意味着一个类型可以安全地发送到其他线程:

note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<std::vec::Vec<(hyper::method::Method, std::string::String, Box<for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static>)>>`
note: required because it appears within the type `MyHandler`
note: required by `hyper::server::Handler`
Run Code Online (Sandbox Code Playgroud)

错误确实指向了正确的位置,但它有点压倒性的.第一行是:

note: `for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static` cannot be sent between threads safely
Run Code Online (Sandbox Code Playgroud)

这是说一种Fn类型没有实现Send.这是您的Route类型中的一个:

type Route = (method::Method, String, Box<Fn(server::Request, server::Response)>);
Run Code Online (Sandbox Code Playgroud)

一个Fn封闭只有Send当所有它捕获的变量也是Send,但在这里我们不知道通过任何罩是否是合适的.

解决方案很简单:将Fn类型约束为Send:

type Route = (method::Method, String, Box<Fn(server::Request, server::Response)+Send>);
Run Code Online (Sandbox Code Playgroud)