I’ve been banging my head about lifetime errors for a few days in Servo, and I’ve reduced my problem to a 100 line example. You can see it at https://gist.github.com/jdm/6d0eda6dbdcbbb13c799 along with the errors I’m receiving.
My problem is this - I have two threads (A and B), and an object O which can only be used on thread B. I want to send a wrapper W for the object to thread A, which will invoke a trait method M on it, passing a closure argument C. This closure C accepts a reference to a trait object; this trait is implemented by the original object O in thread A. Now, this trait method M should cause a message to be sent to thread B which contains the wrapper object W and the closure C. Upon receiving this message, thread A will unwrap the wrapper W, and invoke the closure C, passing the reference to the trait object of O as an argument. With me so far?
The problem here is that in order to pass FnOnce values around between the threads for the closure, I need to pack it up in a Thunk. When this is stored in a struct for sending, the trait object in the thunk’s arguments requires a lifetime bound. That means it’s either
&'a (TraitObject+'a) (or something else like
'static). However, the
'a that gets inferred when I create the struct is much too large, so that when I later unwrap the wrapper object (which is an
Arc<Mutex<Whatever>> in this case), I get a lifetime mismatch.
As far as I can tell this is the problem that higher-rank trait bounds were set up to solve, but I’m stuck because I’m storing this closure type in a struct field, rather than just using it in function arguments. Additionally, any attempt to use
for<'a> Thunk<(...)> fails because Thunk isn’t a trait.
Am I missing something? I’ve tried using
Box<TraitObject+'static> instead of
&'a (TraitObject+'a), but the unwrapped value still doesn’t fulfill the
'static lifetime requirement.