【发布时间】:2018-07-06 18:10:42
【问题描述】:
我正在尝试使用 rlua 将 Lua 脚本添加到我的应用程序,但我遇到了闭包和生命周期问题。
我有一个方法scope,它接受一个闭包作为它的参数。闭包接受一个参数s。我可以在闭包中捕获其他对象,甚至可以将s 传递给它们的方法,前提是我已经正确设置了生命周期。
我想通过使用特征INeedSForSomething 来抽象这些对象,该特征提供了一个可以接受s 的方法need_s。这就是问题开始出现的地方。
scope 在另一个方法 do_scoped_stuff_in_a 中被调用。理想情况下,我想将Box<INeedSForSomething> 传递给此方法,并以s 作为其参数调用need_s。问题是INeedSForSomething trait 必须指定s 的生命周期,以便指定它与包含在实现器中的引用的另一个生命周期的关系。不可能使这个生命周期成为need_s 方法的泛型参数;如果可能的话,其余的代码可以编译得很好。
不幸的是,我不知道我应该如何为INeedSForSomething 提供与闭包参数s 相关的生命周期,这在do_scoped_stuff_in_a 方法之外是未知的。
我想我可以确保通过编写这样的生命周期:<'a: 'scope, 'b: 'scope, 'scope> 'scope 生命周期适合闭包参数,但看起来我在这里遗漏了一些东西......
这是我写的完整代码:
struct A {
//...
}
struct Scope {
//...
}
impl A {
fn scope<F>(&self, f: F)
where
F: FnOnce(&Scope),
{
let scope = Scope {};
f(&scope);
}
}
struct B {
a: A,
}
impl B {
fn do_scoped_stuff_in_a<'a: 'scope, 'b: 'scope, 'scope>(
&'a self,
arg: &'b Box<INeedSForSomething<'scope>>,
) {
self.a.scope(|s| {
arg.need_s(s);
});
}
}
trait INeedSForSomething<'scope> {
fn need_s(&self, scope: &'scope Scope);
}
struct C<'c> {
i_have_a_reference_with_some_lifetime: &'c String,
}
impl<'c: 'scope, 'scope> INeedSForSomething<'scope> for C<'c> {
fn need_s(&self, s: &'scope Scope) {
//...
}
}
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src\main.rs:29:24
|
29 | arg.need_s(s);
| ^
|
note: ...the reference is valid for the lifetime 'scope as defined on the method body at 24:5...
--> src\main.rs:24:5
|
24 | / fn do_scoped_stuff_in_a<'a: 'scope, 'b: 'scope, 'scope>(
25 | | &'a self,
26 | | arg: &'b Box<INeedSForSomething<'scope>>,
27 | | ) {
... |
30 | | });
31 | | }
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the body at 28:22
--> src\main.rs:28:22
|
28 | self.a.scope(|s| {
| ______________________^
29 | | arg.need_s(s);
30 | | });
| |_________^
为熟悉rlua的人提供见解...
我正在尝试创建一个系统,在该系统中我将拥有一个特征,该特征允许我将实现者注册为一个全局回调表,该表在传递给rlua::scope 的闭包内实现实现者的方法。我这样做不是用方法创建UserData,因为我想避免UserData 必须是'static 的限制。 trait 声明的方法需要引用 rlua::Lua 对象以及传递给闭包的 rlua::Scope。不幸的是,如果实现者需要另一个生命周期(例如因为它包含对其他对象的引用),我需要确保 rlua::Scope 的生命周期在这些生命周期的范围内。这导致我必须将rlua::Scope 的生命周期声明为特征声明的一部分。
也许这不是一个好的开始方法,所以如果您对如何创建 Lua 对象有任何更好的想法,让我知道这将允许我改变 Rust 对象的状态而不是 'static。
【问题讨论】: