Зачем нужна доставка статических переменных между методами, а не одним и тем же методом?

Я хочу запустить Hyper-сервер в функции с port а также dao параметры предоставлены main(), но функция работает только после того, как я 'static продолжительность жизни. Это меня сильно смутило.

extern crate futures;
extern crate hyper;

use futures::future::Future;
use hyper::header::ContentLength;
use hyper::server::{Http, Request, Response, Service};
use std::net::SocketAddr;

trait Dao {}

struct MysqlDao;

impl Dao for MysqlDao {}

struct HelloWorld<'a> {
    dao: &'a Dao,
}

const PHRASE: &'static str = "Hello, World!";

impl<'a> Service for HelloWorld<'a> {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, _req: Request) -> Self::Future {
        Box::new(futures::future::ok(
            Response::new()
                .with_header(ContentLength(PHRASE.len() as u64))
                .with_body(PHRASE),
        ))
    }
}

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    let dao = MysqlDao;
    let server = Http::new()
        .bind(&addr, move || Ok(HelloWorld { dao: &dao }))
        .unwrap();
    server.run().unwrap();
}

Http::new().bind Документация API говорит, что нужно NewService + 'staticтак что я думаю, что компилятор выведет dao вариант есть 'static, но когда я убираю последние три утверждения из основного, это не может выводить!

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    let dao: MysqlDao = MysqlDao;
    web_startup(&addr, &dao);
}

fn web_startup<T: Dao>(addr: &SocketAddr, dao: &T) {
    let server = Http::new()
        .bind(addr, move || Ok(HelloWorld { dao }))
        .unwrap();
    server.run().unwrap();
}

Я получаю ошибку:

error[E0477]: the type `[closure@src/main.rs:44:21: 44:51 dao:&T]` does not fulfill the required lifetime
  --> src/main.rs:44:10
   |
44 |         .bind(addr, move || Ok(HelloWorld { dao }))
   |          ^^^^
   |
   = note: type must satisfy the static lifetime

Итак, я исправил это:

fn main() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    static DAO: MysqlDao = MysqlDao;
    web_startup(&addr, &DAO);
}

fn web_startup<T: Dao>(addr: &SocketAddr, dao: &'static T) {
    let server = Http::new()
        .bind(addr, move || Ok(HelloWorld { dao }))
        .unwrap();
    server.run().unwrap();
}

Я не понимаю, почему я должен использовать static ключевое слово для static DAO: MysqlDao = MysqlDao; заявление, но не нужно, прежде чем изменить код. Компилятор не может сделать вывод, или я думаю о вещах неправильно?

1 ответ

Решение

Причина, по которой компилятор не может сделать вывод, что единственный раз web_startup функция будет называться это вызывается с 'static потому что это не гарантировано. Что, если функция была общедоступной и вызывалась сторонним модулем? Компилятор должен сказать конечному пользователю использовать 'static на функции, которая, кажется, не требует таковой. Что делать, если какое-то время в будущем eval() добавлен в Rust (например, для REPL), чтобы даже ваша частная функция могла быть вызвана с неожиданными параметрами функции?

Вы просите сделать вывод, которого не должно быть.

Другие вопросы по тегам