将非静态生命周期传递给Rocket的管理函数

4
我该如何将一个生命周期非静态的对象传递给Rocket的manage方法?目前我的代码大致如下:
fn foo<'a>(bar: Bar<'a>) -> Result<(), Error> {
  rocket::ignite()
    .manage(bar)
    .mount("/", routes![index])
    .launch();

  Ok(())
}

但我收到了以下错误提示:
cannot infer an appropriate lifetime due to conflicting requirements

note: ...so that the expression is assignable:
      expected bar::Bar<'_>
         found bar::Bar<'a>
note: but, the lifetime must be valid for the static lifetime...

为了提供更多的背景信息,Bar 是一个 struct,其中包含使用运行时参数初始化的装箱闭包。这些参数包括密码、密钥和秘密等内容。实际代码是开源的,可以在此处找到。它还在进行中,因此可能会发生变化,并且并非完全最新,但希望可以为最终目标提供一些想法。

1
你不能使用非静态生命周期,因为manage()的签名明确指出了Send + Sync + 'static。你可以尝试修改foo()以接受bar: Bar<'static>而不是通用生命周期,并从那里开始逐步解决问题。只要不捕获非静态生命周期,那么闭包应该是'static的。 - user2722968
谢谢回复。如果那是答案,能否请您将其发布为答案?不幸的是,这似乎有限制,您知道为什么它被明确声明为“静态”的吗? - Will Squire
1个回答

8
因为manage()的签名字面上表示为Send + Sync + 'static,所以您不能使用非静态生命周期。这是在State文档中指明的原因:
被管理的类型必须是线程安全的,并且可以跨线程边界发送。换句话说,它必须实现Send + Sync + 'static。
也就是说,由于(工作)线程可能随时访问被管理的状态,并且因为这些线程何时退出没有保证,所以被管理的状态必须至少与整个程序一样长寿;即 'static
您可以尝试将您的foo()更改为接受bar: Bar<'static>而不是通用生命周期,然后逐步推进。需要'static的要求通常并不像听起来那么糟糕,因为所有拥有所有权的值(如String::new())只要不包含对其他内容的引用,就是'static
如果您无法提供Bar<'static>,则可以尝试使用Arc替代普通引用,使得Bar<'a>变成Bar。这里的原理是Bar保持原子计数引用而不是引用,因此持有一个Bar可以保证在Bar存活时所有成员都是活着的。这使得Bar成为'static
顺便说一下:当思考'static时,了解某种类型需要'static的要求并不意味着该值实际上会永远存在。它只是意味着该值可以被强制存活。在您的情况下,State没有办法强制其他线程不退出并销毁其值。因此,State必须保证它操作的所有值都可以被强制存活与State想要的时间一样长。只有在线程边界处这些值才是'static

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