2016-03-20 3 views
1

Я пытаюсь создать небольшую веб-службу в Rust, используя Hyper и r2d2, но я сталкиваюсь с некоторыми проблемами, связанными с чертами. Я не могу разобрать сообщение об ошибке, отправленное компилятором, поэтому я надеялся, что кто-то сможет мне помочь."trait core :: ops :: Fn <(Request, Response)> не реализован" для закрытия при прохождении пула соединений с обработчиком Hyper

Рассмотрим следующий код:

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:[email protected]/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(); 
} 

Моя цель состоит в том, чтобы использовать pool в функции hello. Используя закрытие, я подумал, что могу передать переменную окружения, которая все еще соответствует ожиданиям 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 `[[email protected]/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, например, это все набухает, и компилятор не жалуется.

ответ

1

Если мы посмотрим на источник гипер, мы можем видеть, для которых CLOSURES необходимая черта реализуется:

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(); 
} 

нотабене Характеристика Fn(Request, Response) является синтаксическим сахаром для границы с более высоким рангом for<'r> Fn(Request<'r,'r>, Response<'r>). Это связано с тем, что Request и Response являются общими для жизни, поэтому ваша функция должна обрабатывать Request s и Response s от любой срок службы.

 Смежные вопросы

  • Нет связанных вопросов^_^