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 gist:6d0eda6dbdcbbb13c799 · GitHub 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.