"trait core::ops::Fn<(Request, Response)> is not implemented" 用于在将连接池传递给 Hyper 处理程序时关闭
"trait core::ops::Fn<(Request, Response)> is not implemented" for a closure when passing a connection pool to a Hyper handler
我正在尝试使用 Hyper and r2d2 在 Rust 中构建一个小型 Web 服务,但我 运行 遇到了一些有关特征的问题。我无法解析编译器抛出的错误消息,所以我希望有人能帮助我。
考虑以下代码:
extern crate hyper;
extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
use hyper::Server;
use hyper::server::{Request,Response,Handler};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use r2d2::{Pool, PooledConnection};
use postgres::{Connection};
fn connect() -> Pool<PostgresConnectionManager>{
let config = r2d2::Config::default();
let conns = "postgres://abc:abc@localhost/abc";
let manager = PostgresConnectionManager::new(conns, SslMode::None).unwrap();
let pool = r2d2::Pool::new(config, manager).unwrap();
return pool;
}
fn hello(pool: Pool<PostgresConnectionManager>, req: Request, res: Response) {
res.send(b"Hello world").unwrap();
}
fn main() {
let pool = connect();
let dispatch = move |req: Request, res: Response| hello(pool, req, res);
Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
}
我的目标是在函数hello
中使用pool
。我想,通过使用闭包,我可以传递一个环境变量,同时仍然符合 Hyper 的期望。不幸的是,我收到以下错误:
src/main.rs:28:45: 28:61 error: the trait `for<'r, 'r, 'r> core::ops::Fn<(hyper::server::request::Request<'r, 'r>, hyper::server::response::Response<'r>)>` is not implemented for the type `[closure@src/main.rs:27:20: 27:76 pool:r2d2::Pool<r2d2_postgres::PostgresConnectionManager>]` [E0277]
src/main.rs:28 Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
^~~~~~~~~~~~~~~~
src/main.rs:28:45: 28:61 help: run `rustc --explain E0277` to see a detailed explanation
error: aborting due to previous error
这取决于 pool
的类型。例如,如果我尝试传递一个 i64
,它会膨胀并且编译器不会抱怨。
如果我们查看 hyper 的源代码,我们可以看到哪些闭包实现了所需的特性:
impl<F> Handler for F where F: Fn(Request, Response<Fresh>), F: Sync + Send {
fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) {
self(req, res)
}
}
这意味着您的闭包需要实现 Fn(Request, Response) + Sync + Send
才能为您实现 Handler
特征。否则,您需要自己实施。由于您的闭包按值采用 pool
,因此它仅实现 FnOnce(Request, Response)
(在 pool
移入函数时只能调用一次)。
要解决此问题,请改为使用对池的不可变引用,以便可以多次调用您的函数(即实现 Fn(Request, Response)
)。
fn hello(pool: &Pool<PostgresConnectionManager>, req: Request, res: Response) {
res.send(b"Hello world").unwrap();
}
fn main() {
let pool = connect();
let dispatch = move |req: Request, res: Response| hello(&pool, req, res);
Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
}
N.B。 trait Fn(Request, Response)
是高阶 trait bound for<'r> Fn(Request<'r,'r>, Response<'r>)
的语法糖。这是因为 Request
和 Response
在生命周期内都是通用的,所以你的函数必须处理 any[=34= 的 Request
s 和 Response
s ] 生命周期。
我正在尝试使用 Hyper and r2d2 在 Rust 中构建一个小型 Web 服务,但我 运行 遇到了一些有关特征的问题。我无法解析编译器抛出的错误消息,所以我希望有人能帮助我。
考虑以下代码:
extern crate hyper;
extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
use hyper::Server;
use hyper::server::{Request,Response,Handler};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use r2d2::{Pool, PooledConnection};
use postgres::{Connection};
fn connect() -> Pool<PostgresConnectionManager>{
let config = r2d2::Config::default();
let conns = "postgres://abc:abc@localhost/abc";
let manager = PostgresConnectionManager::new(conns, SslMode::None).unwrap();
let pool = r2d2::Pool::new(config, manager).unwrap();
return pool;
}
fn hello(pool: Pool<PostgresConnectionManager>, req: Request, res: Response) {
res.send(b"Hello world").unwrap();
}
fn main() {
let pool = connect();
let dispatch = move |req: Request, res: Response| hello(pool, req, res);
Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
}
我的目标是在函数hello
中使用pool
。我想,通过使用闭包,我可以传递一个环境变量,同时仍然符合 Hyper 的期望。不幸的是,我收到以下错误:
src/main.rs:28:45: 28:61 error: the trait `for<'r, 'r, 'r> core::ops::Fn<(hyper::server::request::Request<'r, 'r>, hyper::server::response::Response<'r>)>` is not implemented for the type `[closure@src/main.rs:27:20: 27:76 pool:r2d2::Pool<r2d2_postgres::PostgresConnectionManager>]` [E0277]
src/main.rs:28 Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
^~~~~~~~~~~~~~~~
src/main.rs:28:45: 28:61 help: run `rustc --explain E0277` to see a detailed explanation
error: aborting due to previous error
这取决于 pool
的类型。例如,如果我尝试传递一个 i64
,它会膨胀并且编译器不会抱怨。
如果我们查看 hyper 的源代码,我们可以看到哪些闭包实现了所需的特性:
impl<F> Handler for F where F: Fn(Request, Response<Fresh>), F: Sync + Send {
fn handle<'a, 'k>(&'a self, req: Request<'a, 'k>, res: Response<'a, Fresh>) {
self(req, res)
}
}
这意味着您的闭包需要实现 Fn(Request, Response) + Sync + Send
才能为您实现 Handler
特征。否则,您需要自己实施。由于您的闭包按值采用 pool
,因此它仅实现 FnOnce(Request, Response)
(在 pool
移入函数时只能调用一次)。
要解决此问题,请改为使用对池的不可变引用,以便可以多次调用您的函数(即实现 Fn(Request, Response)
)。
fn hello(pool: &Pool<PostgresConnectionManager>, req: Request, res: Response) {
res.send(b"Hello world").unwrap();
}
fn main() {
let pool = connect();
let dispatch = move |req: Request, res: Response| hello(&pool, req, res);
Server::http("127.0.0.1:3000").unwrap().handle(dispatch).unwrap();
}
N.B。 trait Fn(Request, Response)
是高阶 trait bound for<'r> Fn(Request<'r,'r>, Response<'r>)
的语法糖。这是因为 Request
和 Response
在生命周期内都是通用的,所以你的函数必须处理 any[=34= 的 Request
s 和 Response
s ] 生命周期。