Solved: How do I satisfy a `'static + FnOnce()` requirement?


#1

I’m trying to call this method:

pub fn call_with_gvl<F, R>(func: F) -> R
where
    F: 'static + FnOnce() -> R,
{   
    thread::call_with_gvl(func)
} 

And when I pass it a closure it complains about the lifetime. If I try to box the closure it says that it does not have a constant size known at compile time.

The closure needs to take in three things within the method I’m writing.


#2

The closure cannot borrow anything from its environment - it must consist of only owned data or references to 'static data (that’s the 'static requirement in the call_with_gvl signature). From the little you’ve said, I suspect your closure is borrowing from the environment. Can you show it?


#3

Here’s the first attempt:

let closure = || {
    call_public_method(self.value(), "==", Some(vec![other.value()]))
};

let result = Thread::call_with_gvl(closure);

And the next

let closure = Box::new(move ||
    call_public_method(self.value(), "==", Some(vec![other.value()]))
);

let result = Thread::call_with_gvl(*closure);

And the error

error[E0477]: the type `[closure@src/class/traits/object.rs:623:23: 625:10 self:&&Self, other:&T]` does not fulfill the required lifetime
   --> src/class/traits/object.rs:627:22
    |
627 |         let result = Thread::call_with_gvl(closure);
    |                      ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: type must satisfy the static lifetime

Both the call_public_method and call_with_gvl are FFI calls across to Ruby through its C API.


#4

Your closure is borrowing self and other. Can you do the following instead:

let v = self.value();
let other = other.value();
let closure = move || call_public_method(v, "==", Some(vec![other]));

#5

Thanks! That got past the Rust compiler. Now I’m on to a separate issue not Rust related. Thanks for the tip!