Skip to content

How to access data outside of a function? (Lifetime complications) #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
haudan opened this issue Jul 14, 2017 · 5 comments
Closed

How to access data outside of a function? (Lifetime complications) #14

haudan opened this issue Jul 14, 2017 · 5 comments

Comments

@haudan
Copy link

haudan commented Jul 14, 2017

Lua::create_function accepts callables of 'static lifetime. This obviously disallows passing a closure with an environment, since they are not 'static. This is raises a question: How can one acces data outside of LuaFunction?

How can one achieve something like the following?

let house = House::new(); // Interior mutability type
globals.set("foo", lua.create_function(|_, _| house.set_on_fire()));

What's the usual pattern to solve this issue?

@jonas-schievink
Copy link
Contributor

jonas-schievink commented Jul 14, 2017

You can use an Rc<RefCell<House>>. Note that the userdata API provides a nicer wrapper around this so you might want to consider using that instead.

Now, I wonder whether it would be okay to accept closures with a different lifetime than 'static, provided they still outlive the Lua instance.

For reference, create_function looks like this:

fn create_function<F>(&self, func: F) -> LuaFunction 
where
    F: 'static + for<'a> FnMut(&'a Lua, LuaMultiValue<'a>) -> LuaResult<LuaMultiValue<'a>>

Could we change it so that the closure only has to outlive the Lua instance? Like this:

fn create_function<'lua, F>(&'lua self, func: F) -> LuaFunction<'lua> 
where
    F: 'lua + for<'a> FnMut(&'a Lua, LuaMultiValue<'a>) -> LuaResult<LuaMultiValue<'a>>

On that note, we could also lift the for<'a> FnMut bound to be FnMut(&'lua Lua .... That way, the closure doesn't have to work with any lifetime 'a, but only with the specific (known) lifetime of the Lua object.

@kyren
Copy link
Contributor

kyren commented Jul 14, 2017

Moving a lot of the 'static lifetimes to 'lua is a good suggestion, and I'll take a look at maybe doing that this weekend sometime. There's a lot of hairiness around the type of callbacks, and I'm not positive what you're saying about giving the parameters the lifetime 'lua is possible, but I don't remember the specifics right now. I'll have better answers once I have a chance to take a look at it.

@kyren kyren closed this as completed in 5b723d5 Jul 20, 2017
@kyren
Copy link
Contributor

kyren commented Jul 20, 2017

So I ended up being able to do this, despite initially being convinced I was going to run into problems. This is actually how LuaCallback was defined before, and I have since changed it, but I don't believe I was thinking about it clearly.

This was the relevant discussion I had about this before, and I now am starting to think I was thinking about it incorrectly. I actually do STILL have some boxed functions with approximately this signature:

Box<for<'lua, 'a> Fn(&'lua Lua, &'a C, LuaMultiValue<'lua>) -> LuaResult<LuaMultiValue<'lua>>>

I think the part that I was missing before is that calling these functions is obviously compatible with the new looser lifetime bounds on callbacks, and I don't HAVE to make these the same signature as the ones stored inside Lua.

This is actually pretty significant, because it allows us possibly to go back to having automatic type deduction on callbacks rather than having to call lua.pack / lua.unpack all the time. I might make a pull request about this soon.

@kyren
Copy link
Contributor

kyren commented Jul 20, 2017

I'm sorry if I closed this issue prematurely, I realized later that it might not have been polite to do that without asking. 5b723d5 solves this partially but arguably not completely, your original example would not necessarily compile, since the function you create may outlive the variable it closes over (any closed over variables actually need a lifetime longer than Lua).

Feel free to reopen if you still find this to be an issue. I have some poorly thought out ideas about creating scope limited wrapper types that may help someday.

@kyren
Copy link
Contributor

kyren commented Aug 1, 2017

This is actually unfixed by 721ffc4, feel free to reopen this issue, though I'm not sure there's a fix for it anymore, or at least not an easy one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants