From 138424e6c494d8aa6e2f5418f5151b76baaba5ee Mon Sep 17 00:00:00 2001 From: David Henningsson Date: Tue, 2 Aug 2016 07:26:25 +0200 Subject: [PATCH] Tree: Closures can no longer borrow their environment :-( This is due to a soundness fix in rustc: https://github.com/rust-lang/rust/pull/35143 Signed-off-by: David Henningsson --- examples/server.rs | 5 +++-- src/tree/factory.rs | 9 +++++---- src/tree/leaves.rs | 21 ++++++++++++--------- src/tree/methodtype.rs | 8 ++++---- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/examples/server.rs b/examples/server.rs index e06c1c57..3c9ccca6 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -26,6 +26,7 @@ fn main() { // We create the signal first, since we'll need it in both inside the method callback // and when creating the tree. let signal = Arc::new(f.signal("HelloHappened", ()).sarg::<&str,_>("sender")); + let signal2 = signal.clone(); // We create a tree with one object path inside and make that path introspectable. let tree = f.tree().add(f.object_path("/hello", ()).introspectable().add( @@ -34,7 +35,7 @@ fn main() { f.interface("com.example.dbustest", ()).add_m( // ...and a method inside the interface. - f.method("Hello", (), |m| { + f.method("Hello", (), move |m| { // This is the callback that will be called when another peer on the bus calls our method. // the callback receives "MethodInfo" struct and can return either an error, or a list of @@ -55,7 +56,7 @@ fn main() { }).outarg::<&str,_>("reply") // We also add the signal to the interface. This is mainly for introspection. - ).add_s(signal.clone()) + ).add_s(signal2) )); // We register all object paths in the tree. diff --git a/src/tree/factory.rs b/src/tree/factory.rs index a013651d..bec08756 100644 --- a/src/tree/factory.rs +++ b/src/tree/factory.rs @@ -35,8 +35,8 @@ impl Factory, ()> { impl Factory, D> { /// Creates a new method for single-thread use. pub fn method(&self, t: T, data: D::Method, handler: H) -> Method, D> - where H: Fn(&MethodInfo, D>) -> MethodResult, T: Into> { - super::leaves::new_method(t.into(), data, Box::new(handler) as Box< as MethodType>::Method>) + where H: 'static + Fn(&MethodInfo, D>) -> MethodResult, T: Into> { + super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>) } } @@ -44,7 +44,7 @@ impl Factory, D> { /// Creates a new method for multi-thread use. pub fn method(&self, t: T, data: D::Method, handler: H) -> Method, D> where H: Fn(&MethodInfo, D>) -> MethodResult + Send + Sync + 'static, T: Into> { - super::leaves::new_method(t.into(), data, Box::new(handler) as Box< as MethodType>::Method>) + super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>) } } @@ -79,6 +79,7 @@ impl, D: DataType> Factory { } +/* #[test] fn create_fn() { let f = Factory::new_fn::<()>(); @@ -86,7 +87,7 @@ fn create_fn() { let m = f.method("test", (), |m| Ok(vec!(m.msg.method_return().append1(&borrow_me)))); assert_eq!(&**m.get_name(), "test"); } - +*/ #[test] fn fn_customdata() { diff --git a/src/tree/leaves.rs b/src/tree/leaves.rs index c642cf62..f3bbc813 100644 --- a/src/tree/leaves.rs +++ b/src/tree/leaves.rs @@ -336,7 +336,7 @@ impl<'a, D: DataType> Property, D> { /// /// For single-thread use. pub fn on_get(mut self, handler: H) -> Property, D> - where H: Fn(&mut arg::IterAppend, &PropInfo, D>) -> Result<(), MethodErr> + 'a { + where H: 'static + Fn(&mut arg::IterAppend, &PropInfo, D>) -> Result<(), MethodErr> { self.get_cb = Some(DebugGetProp(Box::new(handler) as Box<_>)); self } @@ -345,7 +345,7 @@ impl<'a, D: DataType> Property, D> { /// /// For single-thread use. pub fn on_set(mut self, handler: H) -> Property, D> - where H: Fn(&mut arg::Iter, &PropInfo, D>) -> Result<(), MethodErr> + 'a { + where H: 'static + Fn(&mut arg::Iter, &PropInfo, D>) -> Result<(), MethodErr> { self.set_cb = Some(DebugSetProp(Box::new(handler) as Box<_>)); self } @@ -460,21 +460,24 @@ fn test_set_prop() { use tree::{Factory, Access}; use std::cell::{Cell, RefCell}; use std::collections::BTreeMap; + use std::rc::Rc; - let changes = Cell::new(0i32); - let setme = RefCell::new("I have not been set yet!".to_owned()); + let changes = Rc::new(Cell::new(0i32)); + let (changes1, changes2) = (changes.clone(), changes.clone()); + let setme = Rc::new(RefCell::new("I have not been set yet!".to_owned())); + let (setme1, setme2) = (setme.clone(), setme.clone()); let f = Factory::new_fn::<()>(); let tree = f.tree().add(f.object_path("/example", ()).introspectable() .add(f.interface("com.example.dbus.rs", ()) .add_p(f.property::("changes", ()) - .on_get(|i, _| { i.append(changes.get()); Ok(()) })) + .on_get(move |i, _| { i.append(changes1.get()); Ok(()) })) .add_p(f.property::("setme", ()) .access(Access::ReadWrite) - .on_get(|i, _| { i.append(&*setme.borrow()); Ok(()) }) - .on_set(|i, _| { - *setme.borrow_mut() = i.get().unwrap(); - changes.set(changes.get() + 1); + .on_get(move |i, _| { i.append(&*setme1.borrow()); Ok(()) }) + .on_set(move |i, _| { + *setme2.borrow_mut() = i.get().unwrap(); + changes2.set(changes2.get() + 1); Ok(()) })) ) diff --git a/src/tree/methodtype.rs b/src/tree/methodtype.rs index 9e534acd..d6fd9c02 100644 --- a/src/tree/methodtype.rs +++ b/src/tree/methodtype.rs @@ -92,10 +92,10 @@ pub trait MethodType: Sized + Default { #[derive(Default, Debug, Copy, Clone)] pub struct MTFn(PhantomData<*const D>); -impl<'a, D: DataType> MethodType for MTFn { - type GetProp = Fn(&mut IterAppend, &PropInfo) -> Result<(), MethodErr> + 'a; - type SetProp = Fn(&mut Iter, &PropInfo) -> Result<(), MethodErr> + 'a; - type Method = Fn(&MethodInfo) -> MethodResult + 'a; +impl MethodType for MTFn { + type GetProp = Fn(&mut IterAppend, &PropInfo) -> Result<(), MethodErr>; + type SetProp = Fn(&mut Iter, &PropInfo) -> Result<(), MethodErr>; + type Method = Fn(&MethodInfo) -> MethodResult; fn call_getprop(p: &Self::GetProp, i: &mut IterAppend, pinfo: &PropInfo) -> Result<(), MethodErr> { p(i, pinfo) }