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

5
我正在学习Rust,并尝试构建一个基于Hyper的微路由系统(只是为了学习目的,我知道存在框架)。
我不知道如何与hyper::server::Handler共享“复杂”类型。我读取了错误消息,但不幸的是,我不知道如何修复它(大多数情况下,Rust编译器只会提示需要修复什么,但现在我不确定是否理解正确)。
这是我尝试过的一个(非工作)简化示例:
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
}

错误信息如下:

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`

如果我使用一个简单的整数,它就能工作,但是使用 Route 类型却不行。

因此,trait 存在问题,并且有一些与“不能安全地在线程之间发送”的内容。阅读 hyper 文档后,我添加了一个 Mutex,但我可能很蠢,我不知道我在做什么,不确定是应该停止学习 Rust 还是继续尝试。

1个回答

7

你已经接近成功了。

错误提示说,MyHandler 没有实现 Send trait,这意味着该类型不能安全地发送到其他线程:

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`

错误提示确实指向了正确的位置,但是有点让人难以理解。第一行内容为:
note: `for<'r, 'r, 'r> std::ops::Fn(hyper::server::Request<'r, 'r>, hyper::server::Response<'r>) + 'static` cannot be sent between threads safely

这句话的意思是Fn类型没有实现Send。这是你的Route类型中的一种情况。
type Route = (method::Method, String, Box<Fn(server::Request, server::Response)>);

如果一个Fn闭包捕获的所有变量也是Send,那么它只能是Send。但是在这里我们不知道传入的任何闭包是否合适。

解决方案很简单:将Fn类型限制为Send

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

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