Closed poga closed 2 years ago
Yeah, very very much agreed. I'm definitely okay with the idea if you want to take a stab at it, and I might have some more things in the FAQ after you're done as well.
Some of the discussion in the comments you linked may not apply in the near future though if we merge #86, but then that will just make NEW things that need to go in the FAQ.
I'm not sure if this counts as a common problem, but I couldn't figure out how to set the include path for require
. Might just be my lack of knowledge of lua showing though.
@zacps The search path used by Lua loaders is specified in package.path
variable. See the manual for more detail. You might want to read the whole Module
section if you want to customize the behavior of loaders.
But yeah, I don't think this question is specified to rlua
. It's more like a general Lua issue.
I solved that, thanks for the tip. I think I've run into the first problem above.
My goal is to write a type Data
which wraps a lua table and implements MetaMethod::Index
so it can provide some methods/values. One of the methods needs to return a reference to the table that it wraps.
What I want to be able to write is something like:
struct DataTest {
table: RegistryKey
}
impl UserData for DataTest {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Index, |lua, this, k: Value<'lua>| {
Ok(lua.create_function::<Value<'lua>, _, _>(|lua, args| {
Ok(Value::Table(lua.registry_value(&this.table)?))
})?)
});
}
}
Which gives:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src\main.rs:139:57
|
139 | Ok(lua.create_function::<Value<'lua>, _, _>(|lua, args| {
| _________________________________________________________^
140 | | Ok(Value::Table(lua.registry_value(&this.table)?))
141 | | })?)
| |_____________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 138:52...
--> src\main.rs:138:52
|
138 | methods.add_meta_method(MetaMethod::Index, |lua, this, k: Value<'lua>| {
| ____________________________________________________^
139 | | Ok(lua.create_function::<Value<'lua>, _, _>(|lua, args| {
140 | | Ok(Value::Table(lua.registry_value(&this.table)?))
141 | | })?)
142 | | });
| |_________^
= note: ...so that the types are compatible:
expected &&DataTest
found &&DataTest
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src\main.rs:139:57: 141:14 this:&&DataTest]` will meet its required lifetime bounds
--> src\main.rs:139:20
|
139 | Ok(lua.create_function::<Value<'lua>, _, _>(|lua, args| {
| ^^^^^^^^^^^^^^^
I read your comment here, but unfortunately changing the Lua API is not possible in this case. Is there any other workaround?
I have merged the FAQ.
About this particular lifetime issue, the problem is that you can't capture a reference to a non-'static
Rust value (i.e. the DataTest
reference which is only valid inside the meta method) in the closure passed to create_function()
. One way to do it is to use add_meta_function
and capture the user data (as a Lua value) in the inner Lua function using Function::bind()
:
impl UserData for DataTest {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_function(MetaMethod::Index, |lua, (this, _k): (Value<'lua>, Value<'lua>)| {
let f = lua.create_function::<AnyUserData, _, _>(|lua, this| {
let t = this.borrow::<DataTest>()?;
Ok(Value::Table(lua.registry_value(&t.table)?))
})?;
Ok(f.bind(this)?)
});
}
}
I've checked that this compiles at least!
While using
rlua
, I encountered a lot of lifetime problem which are already described in previous issues (e.g. https://github.com/kyren/rlua/issues/20#issuecomment-405751583, https://github.com/kyren/rlua/issues/41, https://github.com/kyren/rlua/issues/74...). After reading those issues, usingrlua
becomes much easier.It would be great if we can collect these design rationale into a FAQ document for beginners to lookup. I can help if you're ok about the idea.
Here's a list of issues/comment I think are really helpful:
Why
'static
lifetime is required when passing data toLua
?How do I store
Table
,Function
, or otherrlua
reference types outside of Lua?