Reputation: 257
How do I pass a method to a function, considering the function takes a "handler" with a static lifetime?
(The exact use case behind this is the creation of an Iron Chain in a struct).
Considering we have the following struct Chain
:
struct Chain
{
f: Box<dyn Fn()>
}
impl Chain
{
fn new(handler: impl Fn() + 'static) -> Self
{
return Chain { f: Box::new(handler) };
}
fn invoke(&self)
{
(self.f)();
}
}
When trying to create an instance of this Chain
using a closure, while also passing a method in the closure...
struct MyStruct
{
the_answer: u32
}
impl MyStruct
{
pub fn run(&self)
{
let closure = || {
println!("Closure called");
self.printer_method(String::from("printer_method")); // <-- Problematic line
};
let chain = Chain::new(closure);
chain.invoke();
}
fn printer_method(&self, msg: String)
{
// Access to self.the_answer
println!("The answer is {}, your message is: {}", self.the_answer, msg);
}
}
...the compiler gives the following error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
I've played with the idea of declaring MyStruct
and its members static, but being able to create multiple independent instances of the struct is a requirement (cf. multiple instances of an Iron web server).
Here's a Playground link.
Upvotes: 0
Views: 304
Reputation: 136
In your closure:
let closure = || {
println!("Closure called");
self.printer_method(String::from("printer_method")); // <-- here
};
You are capturing &MyStruct
because of a method call. Since closures in rust are basically just structs with "call" method, this closure can't be 'static because it would outlive the reference to MyStruct
. The solution is to get generic over this lifetime:
struct Chain<'a>
{
f: Box<dyn Fn() +'a>
}
impl<'a> Chain<'a>
{
fn new(handler: impl Fn() + 'a) -> Self
{
return Chain { f: Box::new(handler) };
}
fn invoke(&self)
{
(self.f)();
}
}
Upvotes: 2