繁体   English   中英

为什么我可以将对非静态局部变量的引用传递给具有“静态绑定”的函数?

[英]Why can I pass a reference to a non-static local variable to a function which has a 'static bound?

我有理解为什么可以写代码的问题

extern crate futures;
extern crate hyper;

use hyper::server::{Http, Request, Response, Service};

struct Environment {}

struct HttpService<'a> {
    pub env: &'a Environment,
}

impl<'a> Service for HttpService<'a> {
    type Request = Request;
    type Response = Response;
    type Future = futures::future::FutureResult<Self::Response, Self::Error>;
    type Error = hyper::Error;

    fn call(&self, _req: Request) -> Self::Future {
        futures::future::ok(Response::new())
    }
}

fn foo() {
    let addr = "127.0.0.1:3000".parse().unwrap();
    let env = Environment {};

    // <<<<< why is the non-static &env accepted here?
    let server = Http::new().bind(&addr, move || Ok(HttpService { env: &env }));

    server.unwrap().run().unwrap();
}

bind()方法定义

fn bind<S, Bd>(&self, addr: &SocketAddr, new_service: S) -> Result<Server<S, Bd>>
where
    S: NewService<Request = Request, Response = Response<Bd>, Error = Error> + 'static,
    Bd: Stream<Item = B, Error = Error>,

这意味着闭包必须具有'static生命周期,通过传递&env违反。

为什么它在上面的代码中工作,但不在

fn bar() {
    use tokio_core::net::TcpListener;

    let addr = "127.0.0.1:3000".parse().unwrap();
    let env = Environment {};

    let mut core = tokio_core::reactor::Core::new().unwrap();
    let handle = core.handle();

    use futures::Stream;
    use futures::Future;

    let listener = TcpListener::bind(&addr, &handle)
        .unwrap()
        .incoming()
        .for_each(move |(socket, addr)| {
            let svc = HttpService { env: &env };
            let fut = Http::<hyper::Chunk>::new()
                .serve_connection(socket, svc)
                .map(|_| ())
                .map_err(|_| panic!("err"));
            handle.spawn(fut);
            Ok(())
        });
}

与预期的生命周期相关的错误失败:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/main.rs:50:42
   |
50 |             let svc = HttpService { env: &env };
   |                                          ^^^^
   |
note: first, the lifetime cannot outlive the lifetime  as defined on the body at 49:19...
  --> src/main.rs:49:19
   |
49 |           .for_each(move |(socket, addr)| {
   |  ___________________^
50 | |             let svc = HttpService { env: &env };
51 | |             let fut = Http::<hyper::Chunk>::new()
52 | |                 .serve_connection(socket, svc)
...  |
56 | |             Ok(())
57 | |         });
   | |_________^
note: ...so that closure can access `env`
  --> src/main.rs:50:42
   |
50 |             let svc = HttpService { env: &env };
   |                                          ^^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `HttpService<'_>` will meet its required lifetime bounds
  --> src/main.rs:53:18
   |
53 |                 .map(|_| ())
   |                  ^^^

更好的是,如何使用更强大的Http::serve_*()函数编写后一部分?

我在用

  • Rust 1.22.1
  • 超0.11.15
  • Tokio-core 0.1.12

通过使用move关键字,您已将Environment变量的所有权转移到闭包。 这意味着闭包本身没有引用 ,因此没有涉及的生命周期。 闭包的返回值有一个与闭包本身相关的生命周期,但这是允许的。

请注意,此案例使用NewService

在Tokio示例中,您调用Handle::spawn ,这需要'static生命周期。 未来有参考Environment不符合这一要求。

请注意,此案例使用Service

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM