Pass around a struct to be mutated by a Fn closure

Here is a contrived example of a code where I am stuck

struct Foo {
    bar: Option<String>,
}

fn baz(foo_arg: &mut Foo) {
    // Additional code that includes declaration of some_local_var
    some_local_var.on_event(|| {  // Fn closure
        foo_arg.bar = Some(ruh);  // ruh is a variable generated by this closure
    });
}

fn main() {
    let foo = Foo { bar: None };
    baz(&mut foo);
}

As expected, the compiler does not pass it as it is unsure about the lifetime of foo. I can declare foo as static but then on_event accepts a Fn closure which does not have mutation capabilities so it fails again. If I use Rc<RefCell<Foo>>, we are back to lifetime errors about foo.

How can I solve it?

Using callbacks is very annoying in Rust, since the callback too must have single-ownership of the things it access. Your options are:

  1. Rc<RefCell<...>>
  2. Message passing channels.

It should be possible to make it work with Rc<RefCell<...>>.

I tried using Rc<RefCell<T>> but the compiler is unable to infer lifetimes and nor providing explicit lifetimes works.

Got it working with use of lazy_static and Mutex but it's not a clean solution and involves use of global state.

You will have to post code, because there is a way to make it work.

There is too much of gtk-rs spaghetti in there across multiple files to put it out here without significant effort.

As noted in the edit of the previous reply, I could get it to work using lazy_static! and Mutex:

lazy_static! {
    static ref FOO: Mutex<Foo> = Mutex::new(foo { bar: None });
}

fn main() {...}

fn baz() { // No longer accepts Foo as arg
    // Additional code that includes declaration of some_local_var
    some_local_var.on_event(|| {  // Fn closure
        FOO.lock().unwrap().bar = Some(ruh);  // ruh is a variable generated by this closure
    });
}

But it's not an elegant solution.

If you post code of your Rc<RefCell<..>>, I can show you how to get it working. What I'm guessing went wrong is that you have to clone the Rc before moving it into the callback.