From f05716deb85e8e458f2a43478c5fae4cb156099b Mon Sep 17 00:00:00 2001 From: kyren Date: Thu, 8 Feb 2018 04:55:26 -0500 Subject: [PATCH] This SHOULD fix the lifetime problem with scope... but it doesn't! The following code should not compile: ``` struct Test { field: i32, } let lua = Lua::new(); lua.scope(|scope| { let mut test = Test { field: 0 }; let f = scope .create_function(|_, ()| { test.field = 42; Ok(()) }) .unwrap(); lua.globals().set("bad!", f).unwrap(); }); ``` yet it does with this commit. However, I have a fix for this, which I do not in any way understand. --- src/lua.rs | 16 ++++++++-------- src/tests.rs | 21 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/lua.rs b/src/lua.rs index a0320e6..a7bf385 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -30,8 +30,8 @@ pub struct Lua { /// Constructed by the `Lua::scope` method, allows temporarily passing to Lua userdata that is /// !Send, and callbacks that are !Send and not 'static. -pub struct Scope<'lua> { - lua: &'lua Lua, +pub struct Scope<'scope> { + lua: &'scope Lua, destructors: RefCell Box>>>, } @@ -319,9 +319,9 @@ impl Lua { /// lifetime of values created through `Scope`, and we know that `Lua` cannot be sent to another /// thread while `Scope` is live, it is safe to allow !Send datatypes and functions whose /// lifetimes only outlive the scope lifetime. - pub fn scope<'lua, F, R>(&'lua self, f: F) -> R + pub fn scope<'scope, F, R>(&'scope self, f: F) -> R where - F: FnOnce(&mut Scope<'lua>) -> R, + F: FnOnce(&mut Scope<'scope>) -> R, { let mut scope = Scope { lua: self, @@ -1036,8 +1036,8 @@ impl Lua { } } -impl<'lua> Scope<'lua> { - pub fn create_function<'scope, A, R, F>(&'scope self, mut func: F) -> Result> +impl<'scope> Scope<'scope> { + pub fn create_function(&self, mut func: F) -> Result> where A: FromLuaMulti<'scope>, R: ToLuaMulti<'scope>, @@ -1071,7 +1071,7 @@ impl<'lua> Scope<'lua> { } } - pub fn create_userdata(&self, data: T) -> Result + pub fn create_userdata(&self, data: T) -> Result> where T: UserData, { @@ -1094,7 +1094,7 @@ impl<'lua> Scope<'lua> { } } -impl<'lua> Drop for Scope<'lua> { +impl<'scope> Drop for Scope<'scope> { fn drop(&mut self) { // We separate the action of invalidating the userdata in Lua and actually dropping the // userdata type into two phases. This is so that, in the event a userdata drop panics, we diff --git a/src/tests.rs b/src/tests.rs index bb721d8..f8ce37a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -695,7 +695,24 @@ fn should_not_compile() { let lua = Lua::new(); let mut r = None; lua.scope(|scope| { - r = Some(scope.create_userdata(MyUserdata(Rc::new(()))).unwrap()); - }); + r = Some(scope.create_userdata(MyUserdata(Rc::new(()))).unwrap()); + }); + + struct Test { + field: i32, + } + + let lua = Lua::new(); + lua.scope(|scope| { + let mut test = Test { field: 0 }; + + let f = scope + .create_function(|_, ()| { + test.field = 42; + Ok(()) + }) + .unwrap(); + lua.globals().set("bad!", f).unwrap(); + }); } */