Closure lifetime issues

I want to use closure for a callback-like design with a late setup and have problems coping with lifetime:
The following code does not compile:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a2f320bba0ab72f6ebdb4be456739379
And the suggestion by compiler to use static does not help either, because of the reference to self in the closure instance.
Is there a way to solve this?

You can't do this. You are trying to create a self-referential type and that's extremely hard to do in Rust. I would recommend trying a solution to your problem. What are you trying to do?

Well, it's simple. in Blah I want to create a closure and pass it to Foo, where it's called. The closure needs to call a fn in Blah.

Rust is very unhappy with cyclic references. Perhaps you can give more context as to what you're actually trying to do?

Perhaps you could pass blah to the closure when you try to call it?

fn setup(&mut self) {
    self.foo = Some(Foo::new(|blah| { blah.callback(); } ));
}

Note that you need to take foo out of the option in order to call it successfully:

fn call_foo(&mut self) {
    // This uses Option::take to remove the Foo from self.
    // This is needed to avoid self being borrowed when trying to give
    // a reference to self to the closure
    if let Some(inner) = self.foo.take() {
        // Call the closure. Note that foo is None while calling the closure.
        (inner.foo)(self);
        // Put the closure back after calling it.
        self.foo = Some(inner);
    }
}

playground

Alternatively you could try reference counting the references to allow having several references to the same thing. See playground for example.

Thanks, this is an interesting approach, but I can't use Rc as my app is no-std.

Narrowing my goal even further, what I want to do is to create a boxed closure that will call a function in a struct. It seems that whatever way I approach it, the reference to the struct has to be 'static.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fc0c50f10aecdba2ec6e99af43ef3fab

Note that Rc is also available in alloc, so if you have access to Box, you have access to Rc.

That said, if you really want, you can likely also solve the issue using raw pointers and unsafe, though then you'll have to manually make sure your references are not dangling.

Yeah,. but it's all so complex for such a simple thing as a callback. :slight_smile:

Unfortunately the ownership model of Rust makes circular references difficult to work with.

Essentially the same problem is discussed here
https://users.rust-lang.org/t/observer-pattern-in-rust/13990

with similar approaches suggested, so I guess I have to live with the complexity.