I want to embed a Lua interpreter (with crate mlua
) and expose to that interpreter a function which returns userdata.
Here is a minimal example, where I replaced mlua
's API by trivial functions with similar type signatures (a few parameters and Result
s have been removed):
#![allow(unused_variables,dead_code)]
#![warn(elided_lifetimes_in_paths)]
use std::marker::{PhantomData};
use std::cell::{Cell};
// Miniature -version of mlua interface
struct Lua();
struct Scope<'lua,'scope>(&'lua Lua, PhantomData<Cell<&'scope ()>>);
struct Function<'lua>(&'lua Lua);
struct AnyUserData<'lua>(&'lua Lua);
impl Lua {
pub fn scope<'lua, 'scope, F, R>(&'lua self, f: F)->R
where F: FnOnce(&Scope<'lua, 'scope>)->R, 'lua: 'scope {
f(&Scope(self, PhantomData::<Cell::<&'scope ()>>))
}
pub fn new()->Self { Self() }
}
impl<'lua, 'scope> Scope<'lua, 'scope> {
pub fn create_function<'callback, F, R>(&'callback self, func: F)->Function<'lua>
where F: 'scope + Fn()->R {
Function(self.0)
}
pub fn create_nonstatic_userdata<T: 'scope>(&self, data: T) -> AnyUserData<'lua> {
AnyUserData(self.0)
}
}
fn main() {
let lua = Lua::new();
lua.scope(|scope| {
let f = || { scope.create_nonstatic_userdata(()) };
scope.create_function(f);
});
}
(compared to the previous example, I made this one quite closer to reality, and indeed the error is not the same).
The function f
should then be made visible to the Lua interpreter.
This code fails to compile with error E0521: borrowed data escapes out of closure; this is caused by the create_function()
call (this error disappears when I remove either of the create_*
calls).
However, I don't see where scope
escapes the closure body: obviously, nothing happens outside of the closure body, and the create_function
return value is dropped at the end of the closure (even before, in this example, since the return value of the call is not even used). Moreover, replacing this function call by its definition (Function(scope.0)
unless I'm mistaken) also makes the code compile.
What is happening here? Surely, exporting functions which build userdata is not a marginal use-case for embedding Lua in a project? How should I do this?